LIMIT 10000,10会发生什么?

LIMIT分页优化
进行分页操作时,通常都会通过偏移量来查询某些数据。然后再加上合适的order by子句, order by的列加上了索引,性能一般都不错,而如果没有对应的索引的话,MySQL则需要做大量的文件排序操作,对于文件排序操作,这里有说明。

Limit 100000,10 会发生什么?
Limit的语法是limit m,n 其中m是偏移量,n代表返回的数据条数。比如limit 0,3 就从第一条数据开始读取后面三个数据(1,2,3 ),limit 2,3就从第三条数据开始读取后面三个数据(3,4,5),但是不要以为limit这样操作会直接定位到第三条数据,还是会扫描前两条数据。回到我们要回答的问题,由于100000这个数字非常大, 查询这么多条数据代价非常高,对于这种情况,有两种办法,一种就是页面中限制分页的数量,另外是优化大偏移量的性能。优化大偏移量的性能最简单的方法是使用索引覆盖扫描,还有的方法就是使用延迟关联,它会让MySQL扫描尽可能少的页面,获取需要访问的记录后再根据关联列回表查询需要的所有列。
MySQL中的排序优化
在MySQL中的ORDER BY有两种排序方式:第一种是利用有序索引获取有序数据,第二种是用文件排序。文件排序是一个成本很高的操作,应该尽量避免。当数据量比较小时,文件排序会在内存中进行,否则在磁盘上进行。文件排序有两种排序算法:两次传输排序和单次传输排序。两次传输算法是旧版本使用的一种算法,原理是读取行指针和需要排序的字段,对其进行排序,然后根据排序结果读取所需要的数据行。这样操作会进行两次数据传输,第二次读取的时候会产生大量的随机I/O,成本极高。单次传输算法是新版本中的,原理是先读取查询所需要的所有列,然后再根据给定的列进行排序,最后返回结果。不再需要从数据表读取两次数据,只需要一次顺序I/O读取所有的数据,无须任何的随机的I/O。缺点是如果需要返回的列非常的多,会额外占用大量的空间。两种算法都有各自的适用场景,没有那种算法更为高效的说法。在MySQL中有一个参数max_length_for_sort_data可以用来决定适用那种排序算法,当查询所有列的总长度不超过这个参数时,MySQL适用单次传输排序算法,否则MySQL会选择两次传输排序算法。

磁盘搜索是巨大的性能瓶颈。当数据量变得非常大以致于缓存性能变得不可能有效
时,该问题变得更加明显。对于大数据库,其中你或多或少地随机访问数据,你可以确信
对读取操作需要至少一次硬盘搜索,写操作需要多次硬盘搜索。要想使该问题最小化,应
使用搜索次数较少的磁盘。
学习解释EXPLAIN将帮助你了解MySQL优化器是如何工作的。要使用EXPLAIN,只需要在查询的SELECT关键字之前加上EXPLIAN这个词,MySQL会在查询上设置一个标志。当执行一个查询时,这个标志会使其返回在执行计划中每一步的信息,而不是执行它。增加EXPLAIN时在查询在FROM子句中包括子查询的情况下,会执行子查询。
们使用EXPLAIN解析SQL执行计划时,如果有下面几种情况,就需要特别关注下了:首先看下 type 这列的结果,如果有类型是 ALL 时,表示预计会进行全表扫描(full table scan)。通常全表扫描的代价是比较大的,建议创建适当的索引,通过索引检索避免全表扫描。
  再来看下 Extra 列的结果,如果有出现 Using temporary 或者 Using filesort 则要多加关注:
  Using temporary,表示需要创建临时表以满足需求,通常是因为GROUP BY的列没有索引,或者GROUP BY和ORDER BY的列不一样,也需要创建临时表,建议添加适当的索引。
  Using filesort,表示无法利用索引完成排序,也有可能是因为多表连接时,排序字段不是驱动表中的字段,因此也没办法利用索引完成排序,建议添加适当的索引。
  Using where,通常是因为全表扫描或全索引扫描时(type 列显示为 ALL 或 index),又加上了WHERE条件,建议添加适当的索引。
其他状态例如:Using index、Using index condition、Using index for group-by 则都还好,不用紧张。
EXPLAIN中的列总是10个列,分别是id、 select_type、 table、 type、 possible_keys、 key、key_len、 ref、 rows、 Extra,只有EXPLAIN EXTENDED在MySQL5.1增加了一个filtered列,EXPLAIN PARTITIONS 增加了一个Partitions列)。
Extra列
这一列包含的是不适合显示在其他列的额外信息。Using index使用覆盖索引。Using filesort代表在进行关联查询时用到了文件排序,并且ORDER BY子句中的所有的列都来自关联的第一个表。MySQL在关联处理第一个表的时候就进行文件排序。Using temporary;Using filesort代表会将关联的结果先存放在一个临时表中,等到所有的关联都结束时,再进行文件排序。

CREATE TABLE grade(
Id int not null ,
Name varchar(10) ,
Level char(5),
Key(name)
);
EXPLAIN SELECT id from grade order by name limit 0,10;

EXPLAIN SELECT id from grade order by level limit 0,10;

type列
表示访问类型,就是MySQL决定如何查找表中的行,下面的访问方法依次从最差到最优。
all
最差的方法,利用全表扫描
index
这个跟全表扫描一样,只是MySQL扫描表时按索引次序进行而不是行。他的主要优点是避免了排序。最大的缺点是要承担按索引次序读取整张表的开销。意味着随机次序访问行,开销很大。如果在Extra列中看到“Using index”,说明使用的是覆盖索引。

range
范围扫描就是一个有限制的索引扫描,开始于索引里的某一点,返回匹配这个值域的行。比全索引扫描好一点,不用遍历全部索引,当MySQL使用索引去查找一系列的值时,例如IN()和OR列表,也会显示为范围查询。
ref
这是一种索引访问,返回所有匹配某个单个值的行,它是查找和扫描的混合体,此类索引访问只有当使用了非唯一性索引或者唯一性索引的非唯一性前缀才会发生。
eq_ref
使用这种索引查找,MySQL知道最多会只会返回一条符合条件的记录。这种访问方法只会在MySQL使用主键或者唯一性索引查找才会看到。
const,system
当MySQL能够对查询的某一部分进行优化并将其转换为一个常量时,就会使用这些访问类型。
NULL
这种方式意味着MySQL能够在优化阶段分解查询语句,在执行阶段甚至不用再访问表或者索引。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章