在 Oracle 中运行速度极慢的 Postgres 查询
Extremely slow Postgres query that runs fast in Oracle
所以我在使用 Oracle 获得一些经验后才开始使用 PostgreSQL,我有这个查询,在 Oracle returns 中需要 200 毫秒,在 Postgres returns 中需要 1.40 分钟。罪魁祸首似乎是
AND product_cost_view.product_type_id = product.product_type_id
当我删除这部分或使用某些 ID 硬编码 product_cost_view.product_type_id
时,它运行得很快。解释计划似乎没有提供和洞察力,它只是说 INDEX SCAN ON TABLE product TOTAL COST 776403 1913 ROWS
。
是的,product_cost_view 是一个视图,我还指出,如果我用 table 替换那个视图,该视图也有 product_type_id,那么它也可以快速工作。我尝试以 100 种不同的形式使用 CTE
和 subselects
,但是当我在带有该视图的 where 子句中使用 product.product_type_id 时,它的工作速度非常慢,我看不到我错过了什么。提前致谢 :)
P.S。是的,我在两个数据库中有完全相同的数据和索引
SELECT COUNT(*)
FROM product
WHERE user_id = 1000000
AND (product_id IN (SELECT DISTINCT product_id
FROM product_cost_view
WHERE user_id = 1000000
AND cost_type = 'X'
AND product_cost_view.product_type_id = product.product_type_id)
);
你能试试这个变体吗:
SELECT COUNT(DISTINCT P.product_id)
FROM product P
INNER JOIN product_cost_view PC
ON P.product_id = PC.product_id
AND P.user_id = PC.user_id
AND P.product_type_id = PC.product_type_id
WHERE P.user_id = 1000000
AND PC.cost_type = 'X'
由于 DISTINCT
,PostgreSQL 无法将子查询展平为连接,因此您是 运行 在 product
中找到的每一行的子查询。
没有看到执行计划很难说,但这应该更快:
SELECT COUNT(*)
FROM product AS p
WHERE p.user_id = 1000000
AND EXISTS (SELECT 1 FROM product_cost_view AS pc
WHERE pc.product_type_id = p.product_type_id
AND pc.product_id = p.product_id
AND pc.user_id = 1000000
AND pc.cost_type = 'X');
所以我在使用 Oracle 获得一些经验后才开始使用 PostgreSQL,我有这个查询,在 Oracle returns 中需要 200 毫秒,在 Postgres returns 中需要 1.40 分钟。罪魁祸首似乎是
AND product_cost_view.product_type_id = product.product_type_id
当我删除这部分或使用某些 ID 硬编码 product_cost_view.product_type_id
时,它运行得很快。解释计划似乎没有提供和洞察力,它只是说 INDEX SCAN ON TABLE product TOTAL COST 776403 1913 ROWS
。
是的,product_cost_view 是一个视图,我还指出,如果我用 table 替换那个视图,该视图也有 product_type_id,那么它也可以快速工作。我尝试以 100 种不同的形式使用 CTE
和 subselects
,但是当我在带有该视图的 where 子句中使用 product.product_type_id 时,它的工作速度非常慢,我看不到我错过了什么。提前致谢 :)
P.S。是的,我在两个数据库中有完全相同的数据和索引
SELECT COUNT(*)
FROM product
WHERE user_id = 1000000
AND (product_id IN (SELECT DISTINCT product_id
FROM product_cost_view
WHERE user_id = 1000000
AND cost_type = 'X'
AND product_cost_view.product_type_id = product.product_type_id)
);
你能试试这个变体吗:
SELECT COUNT(DISTINCT P.product_id)
FROM product P
INNER JOIN product_cost_view PC
ON P.product_id = PC.product_id
AND P.user_id = PC.user_id
AND P.product_type_id = PC.product_type_id
WHERE P.user_id = 1000000
AND PC.cost_type = 'X'
由于 DISTINCT
,PostgreSQL 无法将子查询展平为连接,因此您是 运行 在 product
中找到的每一行的子查询。
没有看到执行计划很难说,但这应该更快:
SELECT COUNT(*)
FROM product AS p
WHERE p.user_id = 1000000
AND EXISTS (SELECT 1 FROM product_cost_view AS pc
WHERE pc.product_type_id = p.product_type_id
AND pc.product_id = p.product_id
AND pc.user_id = 1000000
AND pc.cost_type = 'X');