MySQL排序原理与案例分析(2)

create table t1(id int primary key, c1 int, c2 varchar(128)); insert into t1 values(1,1,'a'); insert into t1 values(2,2,'b'); insert into t1 values(3,2,'c'); insert into t1 values(4,2,'d'); insert into t1 values(5,3,'e'); insert into t1 values(6,4,'f'); insert into t1 values(7,5,'g');

假设每页3条记录,第一页limit 0,3和第二页limit 3,3查询结果如下:

MySQL排序原理与案例分析

我们可以看到 id为4的这条记录居然同时出现在两次查询中,这明显是不符合预期的,而且在5.5版本中没有这个问题。产生这个现象的原因就是5.6针对limit M,N的语句采用了优先队列,而优先队列采用堆实现,比如上述的例子order by c1 asc limit 0,3 需要采用大小为3的大顶堆;limit 3,3需要采用大小为6的大顶堆。由于c1为2的记录有3条,而堆排序是非稳定的(对于相同的key值,无法保证排序后与排序前的位置一致),所以导致分页重复的现象。为了避免这个问题,我们可以在排序中加上唯一值,比如主键id,这样由于id是唯一的,确保参与排序的key值不相同。将SQL写成如下:

select * from t1 order by c1,id asc limit 0,3; select * from t1 order by c1,id asc limit 3,3;

案例2

两个类似的查询语句,除了返回列不同,其它都相同,但排序的结果不一致。
测试表与数据:

create table t2(id int primary key, status int, c1 varchar(255),c2 varchar(255),c3 varchar(255),key(c1)); insert into t2 values(7,1,'a',repeat('a',255),repeat('a',255)); insert into t2 values(6,2,'b',repeat('a',255),repeat('a',255)); insert into t2 values(5,2,'c',repeat('a',255),repeat('a',255)); insert into t2 values(4,2,'a',repeat('a',255),repeat('a',255)); insert into t2 values(3,3,'b',repeat('a',255),repeat('a',255)); insert into t2 values(2,4,'c',repeat('a',255),repeat('a',255)); insert into t2 values(1,5,'a',repeat('a',255),repeat('a',255));

分别执行SQL语句:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/1ecd91cf3cc175af0b703eb61940c131.html