MySQL支持对不带HAVING子句的LIMIT进行优化,主要的优化点包括:
LIMIT对单表扫描的影响:如果索引扫描可用且花费低于全表扫描,则用索引扫描实现LIMIT(LIMIT取很少量的行,否则优化器更倾向于使用全表扫描)。
LIMIT对排序的影响:如果LIMIT和ORDERBY子句协同使用,当取到LIMIT设定个数的有序元组数后,后续的排序操作将不再进行。
LIMIT对去重的影响:如果LIMIT和DISTINCT子句协同使用,当取到LIMIT设定个数的唯一的元组数后,后续的去重操作将不再进行。
LIMIT受分组的影响:如果LIMIT和GROUPBY子句协同使用,GROUPBY按索引有序计算每个组的总数的过程中,LIMIT操作不必计数直到下一个分组开始计算。
LIMIT 0:直接返回空结果集。
另外,如果是单表排序加LIMIT操作的格式如下:
SELECT ... FROM single_table ... ORDER BY non_index_column [DESC] LIMIT [M,]N;
从SQL语法格式中可以看到,LIMIT子句可以有M和N两个参数,这两个参数影响着排序算法,如下从通常的排序算法先介绍没有LIMIT子句时的排序处理过程,接着对存在LIMIT子句时排序算法受到影响后的变化内容进行介绍,以明确LIMIT操作对排序的影响(注意对两者进行对比以掌握LIMIT对排序的影响)。
LIMIT对排序算法的影响如下:
通常排序算法:
扫描表,重复如下步骤直到文件结束(可能生成多个待归并文件)。
把扫描的元组放入排序的缓存(由参数sort_buffer_size设定)直到缓存填满。
把排序缓存中的前N行(如果指定M,则是M+N行)写入一个“待归并文件”。
对归并文件排序。
按序返回所有文件(归并所有文件)的前N行(如果指定M,则跳过M行再取N行)。
受LIMIT操作影响改进的算法:(适用于N/M+N行待排序的元素小于排序缓存)
扫描表,把每一个满足条件的元组插入到一个按排序有序的队列。
如果队列满,则淘汰最后一个再插入新的。
返回前N行(如果指定M,则跳过M行再取N行)。
转载于:https://blog.51cto.com/2853725/1547205