Я создал столбец массива postgresql с индексом GIN, и я пытаюсь выполнить запрос содержимого для этого столбца.С помощью стандартного postgresql я могу заставить это работать правильно, как это:
SELECT d.name
FROM deck d
WHERE d.card_names_array @> string_to_array('"Anger#2","Pingle Who Annoys#2"', ',')
LIMIT 20;
Объяснить, проанализировать:
Limit (cost=1720.01..1724.02 rows=1 width=31) (actual time=7.787..7.787 rows=0 loops=1)
-> Bitmap Heap Scan on deck deck0_ (cost=1720.01..1724.02 rows=1 width=31) (actual time=7.787..7.787 rows=0 loops=1)
Recheck Cond: (card_names_array @> '{"\"Anger#2\"","\"Pingle Who Annoys#2\""}'::text[])
-> Bitmap Index Scan on deck_card_names_array_idx (cost=0.00..1720.01 rows=1 width=0) (actual time=7.785..7.785 rows=0 loops=1)
Index Cond: (card_names_array @> '{"\"Anger#2\"","\"Pingle Who Annoys#2\""}'::text[])
Planning time: 0.216 ms
Execution time: 7.810 ms
К сожалению (в данном случае) я использую QueryDSL с которой я читаю функции массива типа @>
, которые невозможно использовать.Однако этот ответ говорит, что вы можете использовать arraycontains
вместо того, чтобы делать то же самое.Я получил это работает, и он возвращает правильные результаты, но он не использует мой индекс.
SELECT d.name
FROM deck d
WHERE arraycontains(d.card_names_array, string_to_array('"Anger#2","Pingle Who Annoys#2"', ','))=true
LIMIT 20;
Объясните анализ:
Limit (cost=0.00..18.83 rows=20 width=31) (actual time=1036.151..1036.151 rows=0 loops=1)
-> Seq Scan on deck deck0_ (cost=0.00..159065.60 rows=168976 width=31) (actual time=1036.150..1036.150 rows=0 loops=1)
Filter: arraycontains(card_names_array, '{"\"Anger#2\"","\"Pingle Who Annoys#2\""}'::text[])
Rows Removed by Filter: 584014
Planning time: 0.204 ms
Execution time: 1036.166 ms
Это мой код QueryDSL для созданиялогическое выражение:
predicate.and(Expressions.booleanTemplate(
"arraycontains({0}, string_to_array({1}, ','))=true",
deckQ.cardNamesArray,
filters.cards.joinToString(",") { "${it.cardName}#${it.quantity}" }
))
Есть ли способ заставить его использовать мой индекс?Или может быть другой способ сделать это с QueryDSL, чтобы использовать встроенную функцию @>
?