我正在使用的應用程式運行如下查詢:
SELECT
"categories"."id"
FROM
"categories"
WHERE
(
('f' )
OR categories.id NOT IN
(
SELECT
category_id
FROM
category_groups
)
);
這個查詢需要很長時間才能完成,我還沒有看到它完成。我們的“categories”表有 65947 行,我們的“category_groups”表有 131,780 行。
在此查詢上運行“EXPLAIN”時,它表示該查詢將“花費”大量作業(成本=1000.29..109033834.49)。
我編輯了此查詢以洗掉('f') OR子句的該部分,如下面的查詢所示:
SELECT
"categories"."id"
FROM
"categories"
WHERE
(
categories.id NOT IN
(
SELECT
category_id
FROM
category_groups
)
);
這個查詢很快就完成了,當解釋它時它的“成本”要低得多(6283.94..10190.09)。
同樣,如果我將 替換為('f') OR,('t') OR查詢會很快完成,并且成本會下降(回到 6283.94..10190.09)。
Why would adding that ('f') OR clause damage this query's performance so much?
Edit:
Here's the full EXPLAIN (VERBOSE) for the query with ('f') OR
Gather (cost=1000.29..109033834.49 rows=32952 width=4)
Output: categories.id
Workers Planned: 1
-> Parallel Index Only Scan using categories_pkey on public.categories (cost=0.29..109029539.29 rows=19384 width=4)
Output: categories.id
Filter: (NOT (SubPlan 1))
SubPlan 1
-> Materialize (cost=0.00..5295.43 rows=131762 width=4)
Output: category_groups.category_id
-> Seq Scan on public.category_groups (cost=0.00..4121.62 rows=131762 width=4)
Output: category_groups.category_id
And here's the full explain for the query without ('f') OR:
Hash Anti Join (cost=6283.94..10190.09 rows=1131 width=4)
Output: categories.id
Hash Cond: (categories.id = category_groups.category_id)
-> Index Only Scan using categories_pkey on public.categories (cost=0.29..2213.44 rows=65903 width=4)
Output: categories.id
-> Hash (cost=4121.62..4121.62 rows=131762 width=4)
Output: category_groups.category_id
-> Seq Scan on public.category_groups (cost=0.00..4121.62 rows=131762 width=4)
Output: category_groups.category_id
uj5u.com熱心網友回復:
這會FALSE OR阻止 PostgreSQL 將您的NOT IN條件優化為反連接。原因是 PostgreSQL 優化器并沒有為此付出足夠的努力。但是,由于很容易重寫查詢以做得更好(簡單地洗掉FALSE OR),因此沒有理由讓優化器更智能。一個聰明的優化器很慢,更好地優化一個寫得不好的查詢的收益不會超過每個人都必須付出的代價。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/442344.html
標籤:sql postgresql
