Loading

PgSQL外连接分页时出现重复数据

今天工作中遇到的问题。

SELECT * FROM a LEFT JOIN b
	ON a.c = b.d
	LIMIT 20 OFFSET 0;

SELECT * FROM a LEFT JOIN b
	ON a.c = b.d
	LIMIT 20 OFFSET 20;

上面两条是一摸一样的语句,只有OFFSET参数不同,相当于第一条语句显示出第一页的数据,第二条显示出第二页,页大小为20,不同的两页理应不应该有重复数据,但确实出现了。

但当我把公司的两张表弄到我的pgsql上,问题就没了

公司PGSQL版本:12.2
我的PGSQL版本:14.5

最开始怀疑的方向错了,看到版本不同表现不同,就怀疑是优化器的锅了。

img

果然,offset为0和offset为20时所使用的执行计划不同,offset为0时被转成了Right Join,而高版本就没这个问题。

按理来说,Right Join和Left Join也不应该造成结果有差异,因为都是双层循环,主表(在这个例子中是a)在外层循环中。但关键是这个用的又是什么Hash Join。我之前没了解过(好像数据库系统里学过),不过应该是Hash Join使得左右连接产生了不同的结果。

解决办法

  1. 添加Order by确定排序顺序
  2. 关闭hashjoin
  3. 不知道PgSQL有没有索引提示这种东西,如果有的话可以影响执行计划的选择
posted @ 2022-10-18 15:18  yudoge  阅读(369)  评论(0编辑  收藏  举报