【问题标题】:How to force a merge join?如何强制合并连接?
【发布时间】:2015-02-26 16:32:39
【问题描述】:

我的 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 命令后,我看到刨床使用了 Hash Join。在我看来,Merge Join 在这里会更快。我错了吗 ?或者也许刨床使用了 Merge Join,因为查询有像“p.distributor_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)” “ -> 使用 res_prod_reseller_id 对 reseller_product p 进行索引扫描(成本=0.00..8.74 行=1 宽度=20)(实际时间=0.729..0.729 行=0 循环=1)” " 索引条件:(reseller_id = 8)" “过滤器:(distributor_id = 896)” “ -> reseller_product_8 p 上的 Seq 扫描(成本=0.00..96310.79 行=1067876 宽度=20)(实际时间=0.168..3850.121 行=808287 循环=1)” " 过滤器:((distributor_id = 896) AND (reseller_id = 8))" “ -> 哈希(成本=45779.60..45779.60 行=848460 宽度=202)(实际时间=6897.658..6897.658 行=709948 循环=1)” “存储桶:1024 批次:256 内存使用量:417kB” “ -> 对 main_table m 进行 Seq 扫描(成本=0.00..45779.60 行=848460 宽度=202)(实际时间=0.926..2770.997 行=709948 循环=1)”

【问题讨论】:

标签: postgresql join


【解决方案1】:

您的计划提到您要更新近百万行,selecting 数据需要 23 秒,而 updatingselecting 他们需要 26 分钟 >。 updating他们是主要问题而不是用于selecting它的计划

当您主要订购您的结果时,最好使用MERGE JOIN。在您的情况下,HASH JOIN 似乎是合适的选择,因为为什么规划者会浪费时间在不需要时订购结果。您仍然可以通过发出“set enable_hashjoin = off”强制规划器使用MERGE JOIN,但这可能会使查询变慢。

我怀疑表上的任何 触发器/索引 正在更新 main_tablemulti-column index's,其中包含 new_prod。我建议您在更新完记录后禁用触发器和/或添加indexes。您的读/写速度还可能取决于考虑您的硬件的其他因素。

【讨论】:

    【解决方案2】:

    main_tablereseller_product 中的 sku 列在两个表中的类型是否相同?

    reseller_product 是否有此顺序的索引?

    CREATE INDEX I_reseller_product_1 ON reseller_product (distributor_id,reseller_id,sku);
    

    main_table 是否在 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 
                   );
    

    【讨论】:

      猜你喜欢
      • 2016-10-19
      • 1970-01-01
      • 2018-11-18
      • 2010-09-09
      • 2017-10-12
      • 2019-12-12
      • 1970-01-01
      • 2019-04-25
      • 2010-10-23
      相关资源
      最近更新 更多