Postgresql 如何强制合并联接?
我的postgresql数据库中有此查询Postgresql 如何强制合并联接?,postgresql,join,Postgresql,Join,我的postgresql数据库中有此查询 UPDATE main_table m SET new_prod=false FROM reseller_product p WHERE p.distributor_id=896 AND p.sku = m.sku AND p.reseller_id=8; 而且执行时间太长。我在两个表中的sku列上都有索引。使用EXPLAIN命令后,我看到planer使用了散列联接。在我看来,合并联接在这里会更快。我错了吗?或者planer使用合并联接,因为查
UPDATE main_table m
SET new_prod=false
FROM reseller_product p
WHERE p.distributor_id=896
AND p.sku = m.sku
AND p.reseller_id=8;
而且执行时间太长。我在两个表中的sku列上都有索引。使用EXPLAIN命令后,我看到planer使用了散列联接。在我看来,合并联接在这里会更快。我错了吗?或者planer使用合并联接,因为查询有“p.distributor\u id=896”这样的过滤器
PS sku类型为字符变化(50)
“更新(成本=80414.35..228437.71行=848460宽度=212)(实际时间=1582872.917..1582872.917行=0循环=1)”
“->哈希联接(成本=80414.35..228437.71行=848460宽度=212)(实际时间=6906.044..23677.829行=706328循环=1)”
“哈希条件:((p.sku)::text=(m.sku)::text)”
“->追加(成本=0.00..96319.53行=1067877宽度=20)(实际时间=0.909..7426.880行=808287循环=1)”
“->使用分销商产品p上的分销商id进行索引扫描(成本=0.00..8.74行=1宽度=20)(实际时间=0.729..0.729行=0循环=1)”
“索引条件:(经销商id=8)”
“筛选器:(分发服务器\u id=896)”
“->分销商产品上的序列扫描\u 8 p(成本=0.00..96310.79行=1067876宽度=20)(实际时间=0.168..3850.121行=808287循环=1)”
“筛选器:((分销商id=896)和(分销商id=8))”
“->散列(成本=45779.60..45779.60行=848460宽度=202)(实际时间=6897.658..6897.658行=709948循环=1)”
“存储桶:1024批:256内存使用率:417kB”
“->主表m上的顺序扫描(成本=0.00..45779.60行=848460宽度=202)(实际时间=0.926..2770.997行=709948循环=1)”
main\u表中的sku
列和reseller\u产品在这两个表中的类型是否相同
分销商产品是否在此订单中有索引
CREATE INDEX I_reseller_product_1 ON reseller_product (distributor_id,reseller_id,sku);
主表在sku列中是否有索引
CREATE INDEX I_main_table_1 ON main_table (sku);
如果所有问题都是肯定的,请尝试以下方法:
UPDATE main_table m
SET new_prod = false
WHERE EXISTS (SELECT 1
FROM reseller_product p
WHERE p.distributor_id = 896
AND p.reseller_id = 8
AND p.sku = m.sku
);
您的计划提到您正在更新近一百万行,选择
数据需要23秒,而更新
和选择
数据需要26分钟<代码>更新
它们是主要问题,而不是选择
它时使用的计划
当您主要对结果进行排序时,合并联接
将是首选。在您的情况下,HASH JOIN
似乎是一个合适的选择,因为当不需要时,计划员为什么会浪费时间来排序结果。您仍然可以通过发出“set enable\u hashjoin=off”命令,强制计划者使用MERGE JOIN
,但这可能会降低查询速度
我怀疑正在更新的
main\u table
或多列索引中包含新产品的触发器/索引。我建议在完成记录更新后,禁用触发器和/或添加索引。您的读/写速度也可能取决于考虑硬件的其他因素。如果您在此处发布EXPLAIN
计划会更好。您可以同时发布这两个表定义吗?
UPDATE main_table m
SET new_prod = false
WHERE EXISTS (SELECT 1
FROM reseller_product p
WHERE p.distributor_id = 896
AND p.reseller_id = 8
AND p.sku = m.sku
);