Misskey: ハッシュタグ検索が遅い

Created on 19 Feb 2020  ·  6Comments  ·  Source: syuilo/misskey

💡 Summary

🙂 Expected Behavior

☹️ Actual Behavior

📝 Steps to Reproduce

1.
2.
3.

📌 Environment

⚙️Server

Most helpful comment

ANYじゃだめっぽい?

EXPLAIN SELECT * FROM note
WHERE 'a' = ANY("note"."tags")

QUERY PLAN
Limit  (cost=0.00..68.85 rows=2 width=459)
  ->  Seq Scan on note  (cost=0.00..68.85 rows=2 width=459)
        Filter: ('a'::text = ANY ((tags)::text[]))
EXPLAIN SELECT * FROM note
WHERE '{"a"}' <@ "note"."tags" 

QUERY PLAN
Limit  (cost=12.02..18.78 rows=2 width=459)
  ->  Bitmap Heap Scan on note  (cost=12.02..18.78 rows=2 width=459)
        Recheck Cond: ('{a}'::character varying[] <@ tags)
        ->  Bitmap Index Scan on "IDX_NOTE_TAGS"  (cost=0.00..12.02 rows=2 width=0)
              Index Cond: ('{a}'::character varying[] <@ tags)
EXPLAIN SELECT * FROM note
WHERE '{"a"}' && "note"."tags"

QUERY PLAN
Limit  (cost=12.02..18.78 rows=2 width=459)
  ->  Bitmap Heap Scan on note  (cost=12.02..18.78 rows=2 width=459)
        Recheck Cond: ('{a}'::character varying[] && tags)
        ->  Bitmap Index Scan on "IDX_NOTE_TAGS"  (cost=0.00..12.02 rows=2 width=0)
              Index Cond: ('{a}'::character varying[] && tags)

All 6 comments

ANYじゃだめっぽい?

EXPLAIN SELECT * FROM note
WHERE 'a' = ANY("note"."tags")

QUERY PLAN
Limit  (cost=0.00..68.85 rows=2 width=459)
  ->  Seq Scan on note  (cost=0.00..68.85 rows=2 width=459)
        Filter: ('a'::text = ANY ((tags)::text[]))
EXPLAIN SELECT * FROM note
WHERE '{"a"}' <@ "note"."tags" 

QUERY PLAN
Limit  (cost=12.02..18.78 rows=2 width=459)
  ->  Bitmap Heap Scan on note  (cost=12.02..18.78 rows=2 width=459)
        Recheck Cond: ('{a}'::character varying[] <@ tags)
        ->  Bitmap Index Scan on "IDX_NOTE_TAGS"  (cost=0.00..12.02 rows=2 width=0)
              Index Cond: ('{a}'::character varying[] <@ tags)
EXPLAIN SELECT * FROM note
WHERE '{"a"}' && "note"."tags"

QUERY PLAN
Limit  (cost=12.02..18.78 rows=2 width=459)
  ->  Bitmap Heap Scan on note  (cost=12.02..18.78 rows=2 width=459)
        Recheck Cond: ('{a}'::character varying[] && tags)
        ->  Bitmap Index Scan on "IDX_NOTE_TAGS"  (cost=0.00..12.02 rows=2 width=0)
              Index Cond: ('{a}'::character varying[] && tags)

ありがとうございます🥰
TypeORMでそのようにクエリしようとするとエラー出ますね…
'{:tag}' <@ note.tags
QueryFailedError: bind message supplies 8 parameters, but prepared statement "" requires 7

TypeORMでそのようにクエリしようとするとエラー出ますね…

私も書き方わからなかったです…

多分RAWで書けば出来そうですが、SQLインジェクション対策が面倒そう

一応他の案として
これでGINじゃない方のIndexは見てくれるみたい

query.andWhere(`'{}' < note.tags`);
query.andWhere(':tag = ANY(note.tags)', { tag: ps.tag.toLowerCase() });
Limit  (cost=0.28..19.54 rows=1 width=14)
->  Index Only Scan using "IDX_88937d94d7443d9a99a76fa5c0" on note  (cost=0.28..19.54 rows=1 width=14)
Index Cond: (tags > '{}'::character varying[])
Filter: ('a'::text = ANY ((tags)::text[]))

SQLインジェクション対策、一回JSONにして渡してからPostgreSQL側で配列にしたほうが安全そう

Was this page helpful?
0 / 5 - 0 ratings