У меня есть два запроса, которые делают то же самое.1
SELECT *
FROM "Products_product"
WHERE ("Products_product"."id" IN
(SELECT U0."product_id"
FROM "Products_purchase" U0
WHERE (U0."state" = 1
AND U0."user_id" = 5))
AND "Products_product"."state" IN (1,
6,
3)
AND UPPER("Products_product"."title" :: TEXT) LIKE UPPER('%toronto%'))
ORDER BY "Products_product"."title_index" ASC
LIMIT 10;
2
SELECT *
FROM "Products_product"
WHERE ("Products_product"."id" = ANY (ARRAY(
(SELECT U0."product_id"
FROM "Products_purchase" U0
WHERE (U0."state" = 1
AND U0."user_id" = 5))))
AND "Products_product"."state" IN (1,
6,
3)
AND UPPER("Products_product"."title" :: TEXT) LIKE UPPER('%toronto%'))
ORDER BY "Products_product"."title_index" ASC
LIMIT 10;
Единственное отличие состоит в том, что первое использование IN
используется для подзапроса, а второе - =ANY(ARRAY())
.Но второй значительно быстрее, чем первый, примерно в 10 раз.Я выполнил объяснение и получил следующие два результата: 1
Limit (cost=5309.92..5309.93 rows=1 width=1906) (actual time=3414.185..3414.190 rows=10 loops=1)
-> Sort (cost=5309.92..5309.93 rows=1 width=1906) (actual time=3414.184..3414.185 rows=10 loops=1)
Sort Key: "Products_product".title
Sort Method: quicksort Memory: 57kB
-> Nested Loop Semi Join (cost=92.66..5309.91 rows=1 width=1906) (actual time=3385.153..3414.099 rows=16 loops=1)
-> Bitmap Heap Scan on "Products_product" (cost=13.85..256.32 rows=61 width=1906) (actual time=3381.327..3384.430 rows=63 loops=1)
Recheck Cond: ((state = ANY ('{1,6,3}'::integer[])) AND (upper((title)::text) ~~ '%TORONTO%'::text))
Rows Removed by Index Recheck: 1
Heap Blocks: exact=64
-> Bitmap Index Scan on "Products_product_state_id_upper_idx" (cost=0.00..13.83 rows=61 width=0) (actual time=3381.001..3381.001 rows=64 loops=1)
Index Cond: ((state = ANY ('{1,6,3}'::integer[])) AND (upper((title)::text) ~~ '%TORONTO%'::text))
-> Bitmap Heap Scan on "Products_purchase" u0 (cost=78.82..82.84 rows=1 width=4) (actual time=0.467..0.467 rows=0 loops=63)
Recheck Cond: ((product_id = "Products_product".id) AND (user_id = 5))
Filter: (state = 1)
Heap Blocks: exact=16
-> BitmapAnd (cost=78.82..78.82 rows=1 width=0) (actual time=0.465..0.465 rows=0 loops=63)
-> Bitmap Index Scan on "Products_purchase_product_id" (cost=0.00..5.06 rows=84 width=0) (actual time=0.265..0.265 rows=30 loops=63)
Index Cond: (product_id = "Products_product".id)
-> Bitmap Index Scan on "Products_purchase_user_id" (cost=0.00..72.57 rows=3752 width=0) (actual time=0.242..0.242 rows=3335 loops=51)
Index Cond: (user_id = 5)
Planning time: 7.540 ms
Execution time: 3414.356 ms
(22 rows)
2
Limit (cost=7378.07..7378.07 rows=1 width=1906) (actual time=116.559..116.562 rows=10 loops=1)
InitPlan 1 (returns $0)
-> Index Scan using "Products_purchase_user_id" on "Products_purchase" u0 (cost=0.43..7329.83 rows=3752 width=4) (actual time=0.021..15.535 rows=3335 loops=1)
Index Cond: (user_id = 5)
Filter: (state = 1)
-> Sort (cost=48.24..48.25 rows=1 width=1906) (actual time=116.558..116.559 rows=10 loops=1)
Sort Key: "Products_product".title
Sort Method: quicksort Memory: 57kB
-> Bitmap Heap Scan on "Products_product" (cost=44.20..48.23 rows=1 width=1906) (actual time=116.202..116.536 rows=16 loops=1)
Recheck Cond: ((id = ANY ($0)) AND (upper((title)::text) ~~ '%TORONTO%'::text))
Filter: (state = ANY ('{1,6,3}'::integer[]))
Rows Removed by Filter: 2
Heap Blocks: exact=18
-> Bitmap Index Scan on "Products_product_id_upper_idx1" (cost=0.00..44.20 rows=1 width=0) (actual time=116.103..116.103 rows=18 loops=1)
Index Cond: ((id = ANY ($0)) AND (upper((title)::text) ~~ '%TORONTO%'::text))
Planning time: 1.054 ms
Execution time: 116.663 ms
(17 rows)
Из документа нет существенной разницы между IN
или ANY
.Но почему я получаю такую разницу результатов.Имеет ли ANY
преимущество перед IN
в любом случае?
Обновление: Кто-то указал, что этот вопрос может быть продублирован оператором IN против ЛЮБОГО в PostgreSQL .Это своего рода один и тот же вопрос, но ответ на этот вопрос не решил мою проблему, потому что у меня есть более подробный случай, помимо этого ответа.
Но второй вариант каждого не эквивалентендругой.Второй вариант конструкции ANY принимает массив (должен быть фактическим типом массива), тогда как второй вариант IN принимает список значений, разделенных запятыми.Это приводит к различным ограничениям при передаче значений и может также привести к различным планам запросов в особых случаях:
https://dba.stackexchange.com/a/125500/3684
Передача нескольких наборов или массивов значений в функцию
На мой вопрос, это не относится ни к одному из этих вопросов.Я просто передаю один массив в качестве подзапроса.И мой случай точно противоположен первому URL.Мой индекс используется только в ANY
, но не в IN
.В общем, этот ответ не решил мою проблему.
ОБНОВЛЕНИЕ2: Я обновляю индекс: CREATE INDEX ON "Products_product" USING GIST (state, id, upper((title) :: TEXT) gist_trgm_ops);
.Я могу подтвердить, что для обоих запросов это обстоятельство одинаково, это означает, что индекс существовал там, но первый не использует его.
ОБНОВЛЕНИЕ3: Я просто удаляю ARRAY
в коде.Но результат тот же.
explain analyze SELECT *
FROM "Products_product"
WHERE ("Products_product"."id" = ANY(
(SELECT U0."product_id"
FROM "Products_purchase" U0
WHERE (U0."state" = 1
AND U0."user_id" = 5)))
AND "Products_product"."state" IN (1,
6,
3)
AND UPPER("Products_product"."title" :: TEXT) LIKE UPPER('%toronto%'))
ORDER BY "Products_product"."title" ASC
LIMIT 10;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=5309.92..5309.93 rows=1 width=1906) (actual time=228.980..228.983 rows=10 loops=1)
-> Sort (cost=5309.92..5309.93 rows=1 width=1906) (actual time=228.979..228.980 rows=10 loops=1)
Sort Key: "Products_product".title
Sort Method: quicksort Memory: 57kB
-> Nested Loop Semi Join (cost=92.66..5309.91 rows=1 width=1906) (actual time=216.392..228.913 rows=16 loops=1)
-> Bitmap Heap Scan on "Products_product" (cost=13.85..256.32 rows=61 width=1906) (actual time=214.332..215.260 rows=63 loops=1)
Recheck Cond: ((state = ANY ('{1,6,3}'::integer[])) AND (upper((title)::text) ~~ '%TORONTO%'::text))
Rows Removed by Index Recheck: 1
Heap Blocks: exact=64
-> Bitmap Index Scan on "Products_product_state_id_upper_idx" (cost=0.00..13.83 rows=61 width=0) (actual time=214.296..214.296 rows=64 loops=1)
Index Cond: ((state = ANY ('{1,6,3}'::integer[])) AND (upper((title)::text) ~~ '%TORONTO%'::text))
-> Bitmap Heap Scan on "Products_purchase" u0 (cost=78.82..82.84 rows=1 width=4) (actual time=0.215..0.215 rows=0 loops=63)
Recheck Cond: ((product_id = "Products_product".id) AND (user_id = 5))
Filter: (state = 1)
Heap Blocks: exact=16
-> BitmapAnd (cost=78.82..78.82 rows=1 width=0) (actual time=0.212..0.212 rows=0 loops=63)
-> Bitmap Index Scan on "Products_purchase_product_id" (cost=0.00..5.06 rows=84 width=0) (actual time=0.017..0.017 rows=30 loops=63)
Index Cond: (product_id = "Products_product".id)
-> Bitmap Index Scan on "Products_purchase_user_id" (cost=0.00..72.57 rows=3752 width=0) (actual time=0.239..0.239 rows=3335 loops=51)
Index Cond: (user_id = 5)
Planning time: 5.083 ms
Execution time: 229.904 ms
(22 rows)
Я думаю, что это не так с ANY
или ANY(ARRAY())
, это просто разница между IN
и ANY