misskey icon indicating copy to clipboard operation
misskey copied to clipboard

タイムライン取得時にdrive_fileへのクエリ回数を減らす

Open yszkst opened this issue 2 years ago • 12 comments

https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/entities/NoteEntityService.ts#L392 から Noteをレスポンス用に整形するために
https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/entities/NoteEntityService.ts#L307 で
drive_fileへのクエリが画像数分走る

noteテーブルに添付ファイル情報を複数カラムの配列で持っているのは扱いにくいのでdrive_fileへの中間テーブルを作ってJOINしたい。

"fileIds" _varchar NOT NULL DEFAULT '{}'::character varying[],
"attachedFileTypes" _varchar NOT NULL DEFAULT '{}'::character varying[],

手っ取り早いのは絵文字でやっている
await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes));
のような処理追加ですが、配列型保持にしている理由が無ければ思い切ってテーブルを正規化した方がいい気がします。

問題なければAssigneeにしてほしいです

yszkst avatar Feb 26 '23 18:02 yszkst

思い切ってテーブルを正規化した方がいい気がします。

既存のレコードのマイグレーションが大変かもしれないですね

syuilo avatar Feb 26 '23 20:02 syuilo

テーブルの構造を変えない方法としては DriveFileの内容をRedisにキャッシュしてしまうのはどうでしょうか? DriveFileはNoteやUserに比べそこまで更新されるわけではないので、 まだ実装の容易性は高そうだと思いました。 またMisskeyの特性上基本的に同じ投稿が多数のユーザから参照される傾向があるので キャッシュのヒット率も高くなるのではないかと思いました。

pantasystem avatar Feb 26 '23 20:02 pantasystem

とりあえずpackManyでhintとして全ドライブファイルpackManyして渡すのが良いかも?

rinsuki avatar Feb 26 '23 20:02 rinsuki

というかdriveFileのpackManyが適当なのを何とかした方がいいな https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/entities/DriveFileEntityService.ts#L261

rinsuki avatar Feb 26 '23 20:02 rinsuki

drive_fileへの中間テーブルを作ってJOINしたい

ちなみにこうする場合ファイルの並び順ってどのように表現されますか?

syuilo avatar Feb 27 '23 00:02 syuilo

@syuilo とりあえず俺のコメントのやつだけやってみていい?

rinsuki avatar Feb 27 '23 00:02 rinsuki

@syuilo とりあえず俺のコメントのやつだけやってみていい?

👍

syuilo avatar Feb 27 '23 00:02 syuilo

既存のレコードのマイグレーションが大変かもしれないですね

クエリは単純なので画像付き投稿数以上の予想外に時間がかかるというのはないと思います。

misskey=# select id, "fileIds" from note order by "createdAt" desc;
     id     |                                                                           fileIds
------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------
 9bptv53mdq | {9aqx97b2z5,9aqwi3jot3,9aqwhkwxt2,9aqwh8g2t1}
 9bp9h6ryuq | {9bp9h58cup}
 9bp9gaysuo | {9bkqw3snx6}


misskey=# select note.id, u."fileId", u."rank" from note cross join unnest(note."fileIds") with ordinality as u("fileId", "rank") order by note."createdAt" desc;
     id     |   fileId   | rank
------------+------------+------
 9bptv53mdq | 9aqx97b2z5 |    1
 9bptv53mdq | 9aqwi3jot3 |    2
 9bptv53mdq | 9aqwhkwxt2 |    3
 9bptv53mdq | 9aqwh8g2t1 |    4
 9bp9h6ryuq | 9bp9h58cup |    1
 9bp9gaysuo | 9bkqw3snx6 |    1



order byは確認のためなので本来不要

ちなみにこうする場合ファイルの並び順ってどのように表現されますか?

中間テーブルにノート内での順番としてrank を持たせます。
並び変えは取ってきた後にNodeJS側でやれます。

TypeORMで書きやすいかは未確認です。

yszkst avatar Feb 27 '23 03:02 yszkst

これ fileIds に貼ってある index 使う方法ありますかね?一応 fileIds に array_ops のインデックスは貼ってはありますが、このインデックスだと中身がある場合のみ取得みたいなことはできなさそうなので https://www.postgresql.jp/document/14/html/gin-builtin-opclasses.html notes テーブルかたっぱしから舐めることになりませんか?

rinsuki avatar Feb 27 '23 04:02 rinsuki

(あと配列からテーブルにする話は #10134 でやりたい)

rinsuki avatar Feb 27 '23 04:02 rinsuki

わざわざ中間テーブルを作る(fileIdsの配列をノートに直接突っ込みたくない)理由がわかっていない

(packManyでファイルごとに要求しているのは直した方がいいとは思うけど)

tamaina avatar Feb 27 '23 04:02 tamaina

なんの方法でもホームTLが絵師フォロー中なので軽くなれば助かります 🙏

yszkst avatar Feb 27 '23 18:02 yszkst