Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQL データ取得高速化
Search
ham
July 06, 2023
0
390
GraphQL データ取得高速化
tsukiji.graphql #1での発表資料です。
https://tsukiji-graphql.connpass.com/event/281413/
ham
July 06, 2023
Tweet
Share
More Decks by ham
See All by ham
Platform Engineeringのエッセンスを小規模な開発組織に取り入れた事例紹介
ham0215
9
1.5k
開発者の定量・定性データを組み合わせて開発者体験を把握するための取り組み
ham0215
5
1.8k
アジャイルを始めるための基礎を固める
ham0215
1
85
開発者体験を意識した開発チームの生産性向上の取り組み
ham0215
3
890
MySQLのViewを活用した安全なマルチテナントの実現方法
ham0215
2
920
開発パフォーマンスを最大化するための開発体制
ham0215
7
1.6k
今こそ思い出すGraphQLの特徴
ham0215
0
170
DevOpsメトリクスとアウトカムの接続にトライ!開発プロセスを通して計測できるメトリクスの活用方法
ham0215
2
530
CIは5分以内!素早い開発サイクルを支えるCI
ham0215
1
4k
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
Being A Developer After 40
akosma
87
590k
Adopting Sorbet at Scale
ufuk
73
9.1k
How STYLIGHT went responsive
nonsquared
95
5.2k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
YesSQL, Process and Tooling at Scale
rocio
169
14k
Producing Creativity
orderedlist
PRO
341
39k
The Language of Interfaces
destraynor
154
24k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Transcript
GraphQL データ取得高速化 tsukiji.graphql #1 2023/07/06 ham
自己紹介 【略歴】 新卒でSIerとして就職 その後、Web系企業やスタートアップを経てファインディに参画 ファインディではFindy Team+のフロント&バックエンド開発を担当 React+Rails+GraphQL+AWSを使って開発しています 浜田 直人 (ham)
ファインディ株式会社 @hamchance0215
N+1問題
users { id profile { name } } N+1問題 –
userを複数返却するQuery – id fieldはusersテーブルから取得 – profileはprofilesテーブルから取得 # Ruby code def resolve User.all end
users { id profile { name } } N+1問題 –
usersは10件Hit select * from users; – profilesを1件ずつ取得 => N+1問題 select * from profiles where user_id = 1; select * from profiles where user_id = 2; … select * from profiles where user_id = 10;
users { id profile { name } } N+1問題 –
usersに対応するprofileを事前ロード # Ruby code def resolve User.all.preload(:profile) end
users { id profile { name } } N+1問題 –
usersは10件Hit select * from users; – hitしたusersに対応したprofilesを事前ロード select * from profiles where user_id in (1, 2, …, 10);
users { id } N+1問題 – usersは10件Hit select * from
users; – fieldに指定していなくてもprofilesを事前ロー ドしてしまう select * from profiles where user_id in (1, 2, …, 10);
users { id profile { name } } N+1問題 –
usersに対応するprofileを遅延ロード # Ruby code def resolve # fieldにprofileがある場合、profile を取得するuser_idを記憶しておき、最後にま とめて取得する User.all end
N+1問題 – 事前ロード🙅 – 指定していないfieldも読み込んでしまう – 遅延ロード🙆 – 指定されたfieldのみまとめて取得
無駄な計算
user(id:$id) { id reviewCount } 無駄な計算 – userを1件返却するQuery – userが投稿したレビュー数を取得
– reviewsテーブルをcount # Ruby code def resolve(id:) user = User.find_by(id:) { id: user.id, review_count: user.reviews.count, } end
user(id:$id) { id reviewCount } 無駄な計算 – users select *
from users where id = 1; – reviews select count(*) from reviews where user_id = 1;
user(id:$id) { id } 無駄な計算 – reviewCountを指定していなくても reviews.countが計算される # Ruby
code def resolve(id:) user = User.find_by(id:) { id: user.id, review_count: user.reviews.count, } end
user(id:$id) { id } 無駄な計算 – reviewCountを指定していなくても reviews.countが計算される # Ruby
code def resolve(id:) user = User.find_by(id:) { id: user.id, review_count: user.reviews.count, } end reviewCountが指定されているときだけ、 reviews.countが計算されるような実装に変 更する!
無駄な計算 – 常に全てのfieldを計算してしまう🙅 – 指定されたfieldのみ計算🙆
直列で取得
hoge { heavy1 heavy2 } 直列で取得 – heavy1やheavy2は重い処理 – レスポンスまでheavy1+heavy2の処理時間
# Ruby code def resolve { heavy1: Hoge.heavy1_process, heavy2: Hoge.heavy2_process, } end
hoge { heavy1 heavy2 } 直列で取得 – heavy1とheavy2は同時に行われるので遅い 方の時間がレスポンスタイムとなる #
Ruby code def resolve # heavy1, 2を非同期で取得 heavy1 = Hoge.sync_heavy1_process heavy2 = Hoge.sync_heavy2_process { heavy1:, heavy2:, } end
直列で取得 – 直列だと重い場合は並列取得を検討🙆 – 直列でも十分速い場合は問題なし! – 並列取得にすると実装の複雑度が上がるのでメ リットがない場合はやらない方が良い
まとめ
- N+1問題 - 遅延ロードを検討する - 無駄な計算 - fieldが指定されているときだけ計算する - 重いfield
- 並列実行を検討する まとめ