MySQL排序原理及实例分析
排序是数据库的一个基本功能,MySQL也不例外,用户可以通过语句顺序来实现指定结果集的排序。事实上,他们是由报表不仅秩序,通过报表,不同的报表组,而且使用排序。本文将介绍如何使用SQL简单索引避免订货成本,然后介绍了MySQL的实现原理,介绍了内部排序和排序相关参数,最后给出了奇怪的一些例子,排序一致性,解释现象的本质原因。
1。排序优化和索引使用
为了优化SQL语句的排序性能,最好的办法是避免排序,它是利用指标合理的好方法。因为指数本身是有序的,如果我们建立一个合适的指标对需要排序的字段,我们可以跳过排序过程提高SQL查询速度。下面,我用一些典型的SQL来说明SQL可以使用索引来减少排序和SQL不是。假设T1表有一个指数(key_part1 KEY1,key_part2),key2(key2)
A.可以使用索引来避免某种SQL
SELECT * FROM的key_part1 T1秩序,key_part2;
SELECT * FROM T1 WHERE key_part1 = constant ORDER BY key_part2;
SELECT * FROM T1,key_part1 >的key_part1 ASC常数阶;
SELECT * FROM T1,key_part1 = constant1和key_part2 > constant2顺序key_part2;
不能使用索引避免对SQL进行排序。
在多个索引中的排序字段,不能使用索引进行排序。
SELECT * FROM的key_part1,key_part2 T1,key2;
排序键序列和索引中的列顺序不一致,不能使用索引排序。
SELECT * FROM的key_part2 T1秩序,key_part1;
提升顺序不,不能使用索引排序。
SELECT * FROM的key_part1 DESC T1秩序,key_part2 ASC;
/ / key_part1是范围查询,和key_part2不能排序的索引
SELECT * FROM T1,key_part1 >定为key_part2;
2。排序算法实现
避免使用SQL不能排序的索引数据库,实现自身的排序功能来满足用户的需求,使用SQL程序会出现filesort,应该指出的是,filesort并不意味着文件实际上是排序,也有可能是内存排序,主要由sort_buffer_size参数确定结果集的大小。有3种方法来实现MySQL内部排名,包括定期整理、排序和优先级队列排序。它主要涉及3种排序算法:快速排序、归并排序和堆排序。假设表结构和sql语句如下所示:
创建表T1(ID int,COL1,COL2 varchar(64)varchar(64),(64),原col3 varchar);
选择COL1,COL2,col3从T1在col1 > 100阶的COL2;
A.常规排序
(1)。记录表T1的条件
(2)。为每一个记录,记录的主要关键+排序关键字(ID,COL2)放入排序缓冲区
(3)如果排序缓冲器可以存储所有(ID,COL2)对符合要求的,将被排序;否则,如果排序缓冲区已满,将排序和凝固成临时文件。(排序算法快速排序算法)
(4)如果在一个排序中生成一个临时文件,我们需要使用合并排序算法来确保临时文件中的记录是有序的。
(5)。循环执行上述过程,直到满足条件的所有记录都与排序有关。
(6)。扫描排序(ID,COL2),并利用ID返回寻找(col1,col2列选择,col3)
(7)。将得到的结果集返回给用户。
从上面的过程中,无论是文件分类取决于是否排序缓冲区可以包含ID(COL2)对。这个缓冲区的大小是由sort_buffer_size参数控制。此外,一个订单需要两倍的IO,一个是钓鱼(ID,COL2),第二(col1,col2钓鱼,col3),因为结果集的排名是由COL2,所以ID是无序的。第二次,MySQL本身优化。首先,ID排序进入缓冲区前,和缓冲区的大小是由read_rnd_buffer_size控制参数。然后按顺序进行记录,并将随机IO转换为顺序IO。
B.优化排序
除了排序本身,定期整理要求两个额外的IO倍。优化排序方法比传统的排序IO减少二次。主要的区别是,排序缓冲区不(ID,COL2)(COL1,COL2,但是,col3)。由于排序缓冲区包含的所有字段的查询必需的,它可以在排序是没有两数据直接完成返回。这种方式的成本是排序缓冲大小相同(col1,col2可以存储少,col3)比ID和col2。如果排序缓冲区不够大,它可能会导致临时文件被写入,造成额外的IO。当然,MySQL提供的参数max_length_for_sort_data。只有当排序元组小于max_length_for_sort_data,我们可以利用的最优排序的方式,否则我们只能用传统的分类方式。
C.优先级队列排序
为了得到最终的排序结果,不管怎样,我们需要对所有满意的记录进行排序,以便返回。5.6版本在空间级别上按限制m和n语句进行了优化。一种新的排序方法——优先队列的方法,这是由堆排序实现。特征的限制只是解堆排序算法,这类问题,虽然仍需要所有参与排序,排序缓冲区空间的元素可以,但只有一个元组M + N M,N个小场景,基本上不是因为排序缓冲区因为不需要临时文件归并排序问题,升阶,大顶的反应器。最后一堆中的元素由最小的n个元素组成。对于下降顺序,使用小顶反应堆,最后堆中的元素构成最大n元素。
三.排序不一致
案例1
MySQL迁移后从5.5到5.6,发现重复的分页。
测试表和数据:
创建表T1(ID为主键,C1 int,C2 varchar(128));
插入T1值(1,1,'a');
插入T1值(2,2,'b');
插入T1值(3,2,c);
插入T1值(4,2,会);
插入T1值(5,3,e);
插入T1值(6,4,F);
插入T1值(7,5,'克');
假设每3页记录,第一页的限制条件的结果和第二页的限制、查询如下:
我们可以看到,在4号的记录出现在同一时间两个查询,这显然是不一样的预期,也在5.5版中没有这样的问题。造成这种现象的原因是5.6极限m,n语句使用一个优先队列和优先级队列使用堆,作为在上面的例子中,C1 ASC限制0, 3的前3个反应器的尺寸;极限3, 3前6堆的大小。因为C1有2记录,3,和堆排序是不稳定的。(对于相同的键值,它不能保证排序之前的排序与位置一致),导致分页的重复。为了避免这个问题,我们可以在排序中添加唯一的值,比如主键ID,这样id是唯一确保排序键值不同的:
SELECT * FROM C1 T1,ID ASC的限制条件;
SELECT * FROM C1 T1,ID ASC限制3;
案例2
除了不同的返回列之外,两个相似的查询语句是相同的,但是排序结果不一致。
测试表和数据:
创建表T2(ID为主键,地位int,C1,C2,C1 varchar(255)(255),255);
插入的T2值(7,1,'a',重复(A,255),重复(A,255));
插入的T2值(6,2,B,重复(A,255),重复(A,255));
插入的T2值(5,2、C、重复(A,255),重复(A,255));
插入的T2值(4,2,'a',重复(A,255),重复(A,255));
插入的T2值(3,3,B,重复(A,255),重复(A,255));
插入的T2值(4,C,重复(A,255),重复(A,255));
插入的T2值(1,5,'a',重复(A,255),重复(A,255));
分别执行SQL语句:
选择身份,地位,C1,C2从T2力量指数(C1)其中C1 > = B。
选择ID,从T2力量指数状态(C1)其中C1 > = 'b'order的;
执行的结果如下:
看看这两个执行计划是否相同
为了说明这个问题,我在语句中添加了强制索引的提示,以确保C1列索引可以被接受。C1语句用于列索引id,然后返回返回的表。根据C1列值的大小,在C1索引中记录的相对位置如下所示:
(C1,ID)=(B,6),(B,3),(5,C),(C,2),相应的状态值为2324。该数据由表状态排序,然后相对位置变化(6,2,B),(5,C),(3,C),(4,C),这是第二个查询返回结果,为什么第一个查询(6,2,B,5、()C)是为了更换这就是我提到的常规早、B.优化排序的红色部分,你能理解的原因。查询的第一列返回超过max_length_for_sort_data字节数,导致传统的顺序排序,在这种情况下,MySQL的rowid排序,随机IO,IO这样的回报是5,在第一,6和第二在后;使用查询优化的过程,没有过程二次排序的记录数据,保持相对位置,先声明,如果你想使用的优化排序,我们会得到max_length_for_sort_data设置,例如,2048。
以下是一点我的关于MySQL的领域知识(仪器、定位),希望对你有帮助
第一点是,有三个功能(秩序的领域,以指导,以定位)
原表:
用户通过身份
AAA AAA
BBB BBB
CCC认证
DDD DDD
噫噫
FFF FFF
以下是我执行死刑的结果:
SELECT * FROM `的领域为用户`(考察,ID)ASC
用户通过身份
AAA AAA
CCC认证
DDD DDD
噫噫
FFF FFF
BBB BBB
根据研究结果,通过现场秩序的结果(2,3,5,4,1,6)显示为:134562
SELECT * FROM `的领域为用户`(考察,ID)描述
用户通过身份
BBB BBB
AAA AAA
CCC认证
DDD DDD
噫噫
FFF FFF
根据研究结果,通过现场秩序的结果(2,3,5,4,1,6)显示为:213456
SELECT * FROM `通过指导用户`阶('2,3,5,4,ID)ASC
用户通过身份
AAA AAA
FFF FFF
BBB BBB
CCC认证
噫噫
DDD DDD
根据研究结果,通过教学秩序的结果(2,3,5,4,1,6)显示为:162354
SELECT * FROM `通过指导用户`阶('2,3,5,4,ID)描述
用户通过身份
DDD DDD
噫噫
CCC认证
BBB BBB
AAA AAA
FFF FFF
根据研究结果,通过教学秩序的结果(2,3,5,4,1,6)显示为:453216
SELECT * FROM `被定位为用户`(ID,'2,3,5,4 ASC的)
用户通过身份
AAA AAA
FFF FFF
BBB BBB
CCC认证
噫噫
DDD DDD
根据这一结果,结果以定位(2,3,5,4,1,6)显示为:162354
SELECT * FROM `被定位为用户`(ID,'2,3,5,4 DESC)
用户通过身份
DDD DDD
噫噫
CCC认证
BBB BBB
AAA AAA
FFF FFF
根据这一结果,结果以定位(2,3,5,4,1,6)显示为:453216
如果我想在我的一次找到数据库(考察)和以其他身份,你必须先把他依次为(4532),然后从`通过仪器用户`秩序的选择*行('4,5,3,2,ID)、` DESC LIMIT从用户`订单或选择*(ID,找到'4,5,3,2)属性将得到你想要的结果。
用户通过身份
BBB BBB
CCC认证
噫噫
DDD DDD
AAA AAA
FFF FFF