-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DBのクエリが多すぎる #6813
Comments
全部Misskey側で処理している の詳細が知りたい |
例えばタイムラインを取得するクエリを例にすると、取得されることになる各ノートのユーザー情報を予めJOINするようにしているからDBで出来る限りのことはやっている状態ではなかろうか |
packManyがpackを全部並列で呼び出してるのでfindOneが呼ばれまくってると思う 別プロジェクトだけど例 https://github.com/rinsuki/sea/blob/5766344c7463dd856ea27d83a47245d764b14cac/src/db/repositories/post.ts (これも application は手抜いてfindOneを投稿数ぶん呼んでるのでよくない) |
packMany はそれぞれに pack を呼び出していて、pack は渡されたものがオブジェクトなら find せずにそのまま利用しているから新たなクエリは発生しないように見える |
noteのrepositoryだとpopulateEmojisとかだめそう |
populateEmojisはカスタム絵文字が含まれてない限りクエリ発火しなさそうだけど populateMyReaction は毎回発火してそう |
大きいインスタンスでクエリ数稼いでるのがたぶんこの辺 |
それはそうなんだけどカスタム絵文字がめっちゃ付いてるとだいたいおもしろいのでRNされまくって刺さり度上がりそう (まあコーナーケースではある) |
ノート作成はいろいろやることあるからクエリ多いだろうなぁ |
write時のクエリを減らすのはめいめいが言っているように厳しそうだけど、read時のクエリはなんか工夫すれば減らせそうな雰囲気はするな |
populateEmojis は見る感じやってることが複雑だからDBサイドでやるのは難しそう |
packManyの時notesの分集約して一回のクエリで問い合わせればマシになりそう |
あと気になっているのはデータベースという割と頻繁にアクセスされるであろうシステムを地理的に離れたサーバーで動かすのは割と良くあることなんだろうか |
DB分けないとアプリサーバーの数増やせなくない? |
pack系は非アクティブユーザーの分は処理しないからさほど増大しないけど |
サーバー自体を分けるのはあると思うけど、それを地理的に離れている場合でもやるのかなって思った |
離れてると言っても国内だから20msぐらいの遅延だし、地理的に離れてないと以前の震災みたいに影響を受ける |
2リージョン以上で同じアプリ動かす時には素直にやるとDBをどっちかのリージョンに寄せないといけない気がするけどあんまり詳しくない (まあリードレプリカとかでマシにはなるだろうけどそれでもwriteはプライマリに行くはずだし) |
元々はPgpool-IIでロードバランシングしてたけど、クエリが多すぎるせいかPgpool-II噛ませるだけでかなりパフォーマンスが下がる |
一定期間使用がなかったアカウントのミュートとかアンテナは削除するか一時停止みたいな処理しないとダメかなぁ |
負荷を考える上では休眠かどうかは考慮しなくて良いか |
需要の無さそうなautoWatch機能を削除したのでノート作成時のクエリが若干減った |
(需要があったとしてもサーバーサイドでやる必要はない) |
syuilo/Misskey.old@4f24915 とか syuilo/Misskey.old@8aa0891 あたりでクエリ数まあまあ減った |
これやるか |
populateEmojis もまとめて行うようにするか |
やった |
ここまでの諸々の改修の結果 タイムラインを100ノート分、通知を100個分読み込んだ時の総発行クエリ1クエリで3msのオーバーヘッドがあると仮定した場合の時間も併記する before797 (2391ms)
after25 (75ms)
|
フォロワー検索の場合 .innerJoinAndSelect('following.follower', 'follower') フォローされてる検索の場合 .innerJoinAndSelect('following.followee', 'followee') あたりを表結合するといいはず |
あと、API (TL/show) 系でクエリされる場合、必ず (デフォルトのDetailedPackedNoeでは) reply, renote, app は解決されるので
あたりを最初から結合しとくといいかも。 → app以外は既に入ってた |
あと |
syuilo/Misskey.old@d7e7848 |
.leftJoinAndSelect('reply.user', 'replyUser')
.leftJoinAndSelect('renote.user', 'renoteUser') は使われない気がする? |
リプライとRenoteのpackするときは必ずそのユーザーも引っ張ってくるからjoinしてる |
リプライとかrenoteが消えていたときも(今のところ)レコード返したくないからそうしたけど、問題ありそうかな |
replyUser, renoteUser はどこからも参照されてないし、entityにも定義なくないです? |
確認したときはこの書き方でjoinされたと思ったけど、勘違いだったかな |
最初からリプライでもRenoteでもない投稿がまるごと消えちゃう |
というかappがDBに投げるクエリ数の話なのに INNER JOIN か LEFT JOIN かって関係あるの? |
クエリ数で言えば関係ない |
やはりjoinされてたので、第二引数は他のクエリ内で参照するための単なるエイリアス的な扱いでそんなに重要じゃないのかも |
出来ることはやって大分減ったはず |
💡 Summary
毎秒800〜1500ぐらいのクエリがPostgreSQLに飛んでいて、PostgreSQLとMisskeyを違うネットワークに置くと極端に重くなる。
参考GIF(内容が見えないようにリサイズしてます)

🙂 Expected Behavior
DB内部である程度処理してから結果を返す
全部Misskey側で処理している
📝 Steps to Reproduce
📌 Environment
Misskey.io v12.54.0
The text was updated successfully, but these errors were encountered: