Postgresql: mergejoin input data is out of order原因以及解决办法

首先我们要知道,出现这个问题,是由于使用了Merge Join 。但是,参与的其中一个表的数据并没有按期望顺序排序,违反了 Merge Join 的前提条件(即两个输入都按某个键有序)。

举个例子

sql 复制代码
SELECT COUNT(a.id)
FROM table_a a
JOIN table_b b
  ON a.key1 = b.key1
     AND a.key2 = b.key2
     AND b.filter_col = 123456
WHERE
  a.status = 0
  AND a.score > 50000
  AND a.lgth >= 3
  AND a.ptop >= 10000
  AND a.vendor_id != 29;

由于此时已经无法使用EXPLAIN (ANALYZE, BUFFERS) 去分析执行计划,不能判断是a表还是b表、或者两个表都是无序的。所以,将查询拆分,分别去分析执行计划。

1.如果没有相关索引,创建索引即可

2.如果有索引,但是没有使用,考虑是否可选择性不够。

例如filter_col = 123456数据超过总表的30%,此时就不会再走索引。需要想其他办法。

如果filter_col = 123456没有超过总表的30%,那么考虑是否是死元组过多,清理死元组

今天遇到的问题是b表的死元组过多,加上filter_col = 123456条件占了20%,实际上也是很多了,所以导致查询计划生成器没有使用索引,以至于出现mergejoin的错误。

除此以外,还有别的奇技淫巧

1.关闭mergejoin

sql 复制代码
SET enable_mergejoin = off;

2.改写查询,使用exists,不过性能可能会很差