Привет, коллеги-инженеры,
У меня запрос, который работает плохо, и я подумал, что добавление индекса будет простым быстрым решением с положительным влиянием на производительность.
Похоже, Я был неправ, поэтому я здесь, чтобы спросить вашего совета, пожалуйста.
Таблица по сути очень проста и содержит ~ 10000 записей, и выглядит примерно так:
CREATE TABLE phrase
(
phrase_id bigint NOT NULL,
phrase text COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT phrase_pkey PRIMARY KEY (phrase_id),
CONSTRAINT phrase_phrase_key UNIQUE (phrase)
)
После удаления / Создавая индексы, я запустил VACUUM ANALYZE для таблицы перед выполнением каких-либо объяснений / запросов.
Выполнение следующего запроса без индекса занимает около 82 мс, грубое среднее за несколько попыток. 1012 *
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) = ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Seq Scan on phrase (cost=0.00..295.72 rows=100 width=18) (actual time=0.049..5.730 rows=2 loops=1)"
" Filter: (upper(phrase) = ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.135 ms"
"Execution Time: 5.745 ms"
Там может быть несколько фраз, чтобы отступить, поэтому я смотрел на ILIKE следующим образом:
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) ~~* ANY('{*PROTEIN SHAKE,*APPLE PIE}');;
"Seq Scan on phrase (cost=0.00..295.72 rows=2 width=18) (actual time=0.113..19.492 rows=2 loops=1)"
" Filter: (upper(phrase) ~~* ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.081 ms"
"Execution Time: 19.510 ms"
После создания индекса btree, подобного этому:
CREATE INDEX phrase_phrase_idx ON phrase USING BTREE (upper(phrase) text_pattern_ops ASC NULLS LAST)
Запрос на равенство дает следующее объяснение; выполнение этого запроса занимает около 85 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) = ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Index Only Scan using phrase_phrase_btree_idx on phrase (cost=0.29..8.61 rows=2 width=18) (actual time=0.031..0.034 rows=2 loops=1)"
" Index Cond: ((upper(phrase)) = ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Heap Fetches: 0"
"Planning Time: 0.100 ms"
"Execution Time: 0.112 ms"
Запрос ILIKE дает следующее объяснение; Выполнение этого запроса занимает около 95 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) ~~* ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Seq Scan on phrase (cost=0.00..295.72 rows=2 width=18) (actual time=0.116..19.043 rows=2 loops=1)"
" Filter: (upper(phrase) ~~* ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.247 ms"
"Execution Time: 19.060 ms"
Я подумал, что, возможно, стоит попробовать вставить значения в индекс, чтобы сохранить поездку в таблицу:
CREATE INDEX phrase_phrase_idx ON phrase USING BTREE (upper(phrase) text_pattern_ops ASC NULLS LAST) INCLUDE(phrase_id, phrase);
Запуск Следующий запрос (не объяснение) занял около 85 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) = ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Seq Scan on phrase (cost=0.00..295.72 rows=100 width=18) (actual time=0.046..5.734 rows=2 loops=1)"
" Filter: (upper(phrase) = ANY ('{"*)"","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.139 ms"
"Execution Time: 5.748 ms"
, и этот запрос ILIKE занял около 95 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) ~~* ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Seq Scan on phrase (cost=0.00..295.72 rows=2 width=18) (actual time=0.114..19.340 rows=2 loops=1)"
" Filter: (upper(phrase) ~~* ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.094 ms"
"Execution Time: 19.357 ms"
Я думал, что попробую индекс GIN:
CREATE INDEX phrase_phrase_gin_idx ON phrase USING GIN (upper(phrase) gin_trgm_ops)
Запрос приравнивания занял ~ 85 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) = ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Seq Scan on phrase (cost=0.00..295.72 rows=2 width=18) (actual time=0.056..5.764 rows=2 loops=1)"
" Filter: (upper(phrase) = ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Filter: 10046"
"Planning Time: 0.059 ms"
"Execution Time: 5.775 ms"
Запрос ILIKE также занял около 85 мс.
EXPLAIN ANALYSE SELECT phrase FROM phrase WHERE upper(phrase) ~~* ANY('{*PROTEIN SHAKE,*APPLE PIE}');
"Bitmap Heap Scan on phrase (cost=148.02..155.34 rows=2 width=18) (actual time=0.264..0.275 rows=2 loops=1)"
" Recheck Cond: (upper(phrase) ~~* ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
" Rows Removed by Index Recheck: 2"
" Heap Blocks: exact=3"
" -> Bitmap Index Scan on phrase_phrase_gin_idx (cost=0.00..148.02 rows=2 width=0) (actual time=0.247..0.247 rows=4 loops=1)"
" Index Cond: (upper(phrase) ~~* ANY ('{"*PROTEIN SHAKE","*APPLE PIE"}'::text[]))"
"Planning Time: 0.281 ms"
"Execution Time: 0.314 ms"
Я не уверен, что делаю неправильно, но Я не вижу большой пользы в том, как я проиндексировал.
Пожалуйста, кто-нибудь будет достаточно любезен, чтобы указать, где / почему я являюсь пустышкой.
Я бы хотел быть в состоянии существенно изменить этот запрос, но я что-то упустил.
С наилучшими пожеланиями, Пол.