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
370
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
8
1.5k
開発者の定量・定性データを組み合わせて開発者体験を把握するための取り組み
ham0215
4
620
アジャイルを始めるための基礎を固める
ham0215
1
76
開発者体験を意識した開発チームの生産性向上の取り組み
ham0215
3
840
MySQLのViewを活用した安全なマルチテナントの実現方法
ham0215
2
750
開発パフォーマンスを最大化するための開発体制
ham0215
7
1.6k
今こそ思い出すGraphQLの特徴
ham0215
0
160
DevOpsメトリクスとアウトカムの接続にトライ!開発プロセスを通して計測できるメトリクスの活用方法
ham0215
2
500
CIは5分以内!素早い開発サイクルを支えるCI
ham0215
1
3.9k
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
169
14k
What's new in Ruby 2.0
geeforr
343
31k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
410
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
BBQ
matthewcrist
85
9.3k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
Building Applications with DynamoDB
mza
90
6.1k
Why Our Code Smells
bkeepers
PRO
334
57k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Documentation Writing (for coders)
carmenintech
65
4.4k
Into the Great Unknown - MozCon
thekraken
32
1.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
- 並列実行を検討する まとめ