`

转___MySQL Order By索引优化

 
阅读更多

在一些情况下,MySQL可以直接使用索引来满足一个 ORDER BY 或 GROUP BY 子句而无需做额外的排序。尽管 ORDER BY 不是和索引的顺序准确匹配,索引还是可以被用到,只要不用的索引部分和所有的额外的 ORDER BY 字段在 WHERE 子句中都被包括了。

 

使用索引的MySQL Order By
下列的几个查询都会使用索引来解决 ORDER BY 或 GROUP BY 部分: 
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; 
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2; 
SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2; 
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC; 
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; 

 

不使用索引的MySQL Order By
在另一些情况下,MySQL无法使用索引来满足 ORDER BY,尽管它会使用索引来找到记录来匹配 WHERE 子句。这些情况如下: 
* 对不同的索引键做 ORDER BY : 
SELECT * FROM t1 ORDER BY key1, key2; 
* 在非连续的索引键部分上做 ORDER BY: 
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2; 
* 同时使用了 ASC 和 DESC: 
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC; 
* 用于搜索记录的索引键和做 ORDER BY 的不是同一个:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1; 
* 有很多表一起做连接,而且读取的记录中在 ORDER BY 中的字段都不全是来自第一个非常数的表中(也就是说,在 EXPLAIN 分析的结果中的第一个表的连接类型不是 const)。 
* 使用了不同的 ORDER BY 和 GROUP BY 表达式。
* 表索引中的记录不是按序存储。例如,HASH 和 HEAP 表就是这样。

 

通过执行 EXPLAIN SELECT ... ORDER BY,就知道MySQL是否在查询中使用了索引。如果 Extra 字段的值是 Using filesort,则说明MySQL无法使用索引。详情请看"7.2.1 EXPLAIN Syntax (Get Information About a SELECT)"。当必须对结果进行排序时,MySQL 4.1以前 它使用了以下 filesort 算法:

1. 根据索引键读取记录,或者扫描数据表。那些无法匹配 WHERE 分句的记录都会被略过。
2. 在缓冲中每条记录都用一个‘对’存储了2个值(索引键及记录指针)。缓冲的大小依据系统变量 sort_buffer_size 的值而定。 
3. 当缓冲慢了时,就运行 qsort(快速排序)并将结果存储在临时文件中。将存储的块指针保存起来(如果所有的‘对’值都能保存在缓冲中,就无需创建临时文件了)。 
4. 执行上面的操作,直到所有的记录都读取出来了。 
5. 做一次多重合并,将多达 MERGEBUFF(7)个区域的块保存在另一个临时文件中。重复这个操作,直到所有在第一个文件的块都放到第二个文件了。 
6. 重复以上操作,直到剩余的块数量小于 MERGEBUFF2 (15)。 
7. 在最后一次多重合并时,只有记录的指针(排序索引键的最后部分)写到结果文件中去。
8. 通过读取结果文件中的记录指针来按序读取记录。想要优化这个操作,MySQL将记录指针读取放到一个大的块里,并且使用它来按序读取记录,将记录放到缓冲中。缓冲的大小由系统变量 read_rnd_buffer_size 的值而定。这个步骤的代码在源文件 `sql/records.cc' 中。

这个逼近算法的一个问题是,数据库读取了2次记录:一次是估算 WHERE 分句时,第二次是排序时。尽管第一次都成功读取记录了(例如,做了一次全表扫描),第二次是随机的读取(索引键已经排好序了,但是记录并没有)。在MySQL 4.1 及更新版本中,filesort 优化算法用于记录中不只包括索引键值和记录的位置,还包括查询中要求的字段。这么做避免了需要2次读取记录。改进的 filesort 算法做法大致如下:


1. 跟以前一样,读取匹配 WHERE 分句的记录。
2. 相对于每个记录,都记录了一个对应的;‘元组’信息信息,包括索引键值、记录位置、以及查询中所需要的所有字段。 
3. 根据索引键对‘元组’信息进行排序。 
4. 按序读取记录,不过是从已经排序过的‘元组’列表中读取记录,而非从数据表中再读取一次。 

使用改进后的 filesort 算法相比原来的,‘元组’比‘对’需要占用更长的空间,它们很少正好适合放在排序缓冲中(缓冲的大小是由 sort_buffer_size 的值决定的)。因此,这就可能需要有更多的I/O操作,导致改进的算法更慢。为了避免使之变慢,这种优化方法只用于排序‘元组’中额外的字段的大小总和超过系统变量 max_length_for_sort_data 的情况(这个变量的值设置太高的一个表象就是高磁盘负载低CPU负载)。想要提高 ORDER BY 的速度,首先要看MySQL能否使用索引而非额外的排序过程。如果不能使用索引,可以试着遵循以下策略:

* 增加 sort_buffer_size 的值。 
* 增加 read_rnd_buffer_size 的值。 
* 修改 tmpdir,让它指向一个有很多剩余空间的专用文件系统。

 

如果使用MySQL 4.1或更新,这个选项允许有多个路径用循环的格式。各个路径之间在 Unix 上用冒号(':')分隔开来,在 Windows,NetWare以及OS/2 上用分号(';')。可以利用这个特性将负载平均分摊给几个目录。注意:这些路径必须是分布在不同物理磁盘上的目录,而非在同一个物理磁盘上的不同目录。

 

优化嵌套查询 
MySQL4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个查询结果作为过滤条件用在另一个查询中,使用子查询可以一次性地完成多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且些起来也很容易。但是,有些情况下,子查询可以被更有效的连接(JOIN)替代。 
例如: 
explain select * from sales2 where company_id not in(select id from company2) \G 
explain select * from sales2 left join comany2 on sales2.company_id = company2.id  where sales2.company_id is null \G; 
第一句看起来比第二句更简洁,但是第二句比第一就更快。因为使用JOIN来完成这个查询,速度比较快,尤其如果对compay2表中的id建立了索引的话,那么性能将会更好。那为什么在这种情况下使用JOIN会更有效率呢。因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。 
优化OR条件 
对于含有OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引;如果没有索引,则考虑增加索引。 
使用SQL提示 
SQL 提示(SQL HINT)是优化数据库的一个重要手段,简单来说就是在SQL语句中加入一些人为的提示来达到优化的操作的目的。 
例如: 
SELECT SQL_BUFFER_RESULTS * FROM ... 
这个语句将强制MySQL生成一个临时结果集。只要临时结果集生成后,所有表上的锁定均被释放。这能在遇到表锁定问题时或者要花很长时间将结果传给客户端时所帮助,因为可以尽快释放锁资源, 
下面是一些在MySQL中常用的SQL提示。 
1. USE INDEX 
在查询语句中表名的后面,添加USE INDEX 来提供希望MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。 
    
引用
       explain select * from sales2 use index (ind_sales2_id) where id  3 \G; 
   
2. IGNORE INDEX 
     如果用户只是单纯地想让MySQL忽略一个或者多个索引,则可以使用IGNORE INDEX 作为HINT 
3. FORCE INDEX 
  为强制MySQL使用一个特定的索引,可在查询中使用FORCE INDEX作为HINT。例如当不强制使用索引的时候,因为id的值都是大于0的,因为MySQL会默认进行全表扫描,而不使用索引。例如: 
引用
  expalin select * from sales2 where id > 0 \G; 
但是,当使用FORCE INDEX进行提示时,即便使用索引的效率不是很高,MySQL还是选择使用了索引,这是MySQL留给用户的一个自行选择执行计划的权利。加入FORCE INDEX提示后在执行上面的SQL 
引用
    explain select * from sales2 force index(index_sales2_id) where id > 0 \G; 
  SQL优化问题是数据库性能优化最基础也是最重要的一个问题,实践表明很多数据库性能问题都是由于不合适的SQL语句造成。一些列的SQL优化描述。怎么定位问题,怎么在编写的时候优化,怎么来应对。不过优化SQL语句经常需要考虑的几个方面,比如索引,表分析,排序等等。

优化嵌套查询 
MySQL4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个查询结果作为过滤条件用在另一个查询中,使用子查询可以一次性地完成多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且些起来也很容易。但是,有些情况下,子查询可以被更有效的连接(JOIN)替代。 
例如:

 

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->explain select * from sales2 where company_id not in(select id from company2) \G explain select * from sales2 left join comany2 on sales2.company_id = company2.id where sales2.company_id is null \G;

 

 

 

第一句看起来比第二句更简洁,但是第二句比第一就更快。因为使用JOIN来完成这个查询,速度比较快,尤其如果对compay2表中的id建立了索引的话,那么性能将会更好。那为什么在这种情况下使用JOIN会更有效率呢。因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。 
优化OR条件 
对于含有OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引;如果没有索引,则考虑增加索引。 
使用SQL提示 
SQL 提示(SQL HINT)是优化数据库的一个重要手段,简单来说就是在SQL语句中加入一些人为的提示来达到优化的操作的目的。 例如: 

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->SELECT SQL_BUFFER_RESULTS * FROM ...

 

 
这个语句将强制MySQL生成一个临时结果集。只要临时结果集生成后,所有表上的锁定均被释放。这能在遇到表锁定问题时或者要花很长时间将结果传给客户端时所帮助,因为可以尽快释放锁资源, 


下面是一些在MySQL中常用的SQL提示。 
1. USE INDEX 
在查询语句中表名的后面,添加USE INDEX 来提供希望MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。 
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->explain select * from sales2 use index (ind_sales2_id) where id 3 \G; 

2. IGNORE INDEX 

如果用户只是单纯地想让MySQL忽略一个或者多个索引,则可以使用IGNORE INDEX 作为HINT 
3. FORCE INDEX   

为强制MySQL使用一个特定的索引,可在查询中使用FORCE INDEX作为HINT。例如当不强制使用索引的时候,因为id的值都是大于0的,因为MySQL会默认进行全表扫描,而不使用索引。例如:

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->expalin select * from sales2 where id > 0 \G;
但是,当使用FORCE INDEX进行提示时,即便使用索引的效率不是很高,MySQL还是选择使用了索引,这是MySQL留给用户的一个自行选择执行计划的权利。加入FORCE INDEX提示后在执行上面的SQL
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->explain select * from sales2 force index(index_sales2_id) where id > 0 \G;

 

  SQL优化问题是数据库性能优化最基础也是最重要的一个问题,实践表明很多数据库性能问题都是由于不合适的SQL语句造成。一些列的SQL优化描述。怎么定位问题,怎么在编写的时候优化,怎么来应对。不过优化SQL语句经常需要考虑的几个方面,比如索引,表分析,排序等等。

<script type="text/javascript"></script>
分类: Mysql
分享到:
评论

相关推荐

    MySQL Order By索引优化方法

    总之,理解`ORDER BY`和`GROUP BY`的索引优化策略,以及如何通过`EXPLAIN`分析查询计划,可以帮助我们有效地优化查询,避免不必要的`filesort`操作,从而提升MySQL数据库的性能。在设计索引时,应考虑查询语句的常见...

    MySQL 通过索引优化含ORDER BY的语句

    MySQL数据库在处理含`ORDER BY`的SQL语句时,索引优化是非常关键的一环,因为这直接影响到查询性能。以下是一些关于如何利用索引来优化`ORDER BY`语句的知识点: 1. **合理创建索引**:索引可以显著提高数据读取...

    尚硅谷Java视频教程_MySQL高级视频

    尚硅谷_MySQL高级_为排序使用索引OrderBy优化 · 49.尚硅谷_MySQL高级_慢查询日志 · 50.尚硅谷_MySQL高级_批量插入数据脚本 · 51.尚硅谷_MySQL高级_用Show Profile进行sql分析 · 52.尚硅谷_MySQL高级_全局...

    mysql索引优化分享

    关于mysql索引一些优化介绍与创建原则,还有对order by排序的算法的介绍等等

    MySQL利用索引优化ORDER BY排序语句的方法

    创建表&创建索引 create table tbl1 ( id int unique, sname varchar(50), index tbl1_index_sname(sname desc...通过索引优化来实现MySQL的ORDER BY语句优化: 1、ORDER BY的索引优化 如果一个SQL语句形如: SELECT

    mysql_cn_sc.rar_mysql 中文_mysql手册_sql mysql

    此外,还有更高级的SQL特性,如联接(JOIN)、子查询、聚合函数(COUNT, SUM, AVG等)、分组(GROUP BY)和排序(ORDER BY)等。 MySQL支持多种存储引擎,如InnoDB(支持事务处理和外键)、MyISAM(快速读取但不...

    MYSQL order by排序与索引关系总结1

    MySQL中的ORDER BY排序与索引关系是数据库性能优化的关键因素之一。本文主要针对InnoDB存储引擎的B-Tree索引进行探讨,不涉及索引设计,而是关注如何有效利用索引来提升查询性能。 首先,遵循**最左前缀法则**是...

    MySQL的or、in、union与索引优化

    ### MySQL的or、in、union与索引优化 在数据库查询优化中,索引的使用至关重要,它能显著提升查询速度。本文将基于一个具体的业务场景来探讨在MySQL中使用`union all`、`in`、`or`以及负向查询(如`!=`)时如何有效...

    Mysql索引优化案例.pdf

    Mysql索引优化案例 在对数据库进行操作时,尤其是在处理包含大量数据的表时,查询的性能问题是一个常见且重要的话题。在实际工作中,对于Mysql数据库进行索引优化是提高查询效率、减少查询时间的重要手段。本案例将...

    mysql查询优化之索引优化

    - **选择合适的索引列**:索引应该建在经常出现在WHERE子句、JOIN条件和ORDER BY子句中的列上。 - **避免过度索引**:过多的索引会增加写操作的开销,因此需要权衡读写性能。 - **复合索引**:如果一个查询涉及多...

    mysql高级视频教程百度云(2019).txt

    48.MySQL高级_为排序使用索引OrderBy优化.avi 47.MySQL高级_in和exists.avi 46.MySQL高级_小表驱动大表.avi 45.MySQL高级_索引优化答疑补充和总结口诀.avi 44.MySQL高级_索引面试题分析.avi 43.MySQL高级...

    MySQL中索引优化distinct语句及distinct的多字段操作

    MySQL通常使用GROUPBY(本质上是排序动作)完成DISTINCT操作,如果DISTINCT操作和ORDERBY操作组合使用,通常会用到临时表.这样会影响性能. 在一些情况下,MySQL可以使用索引优化DISTINCT操作,但需要活学活用.本文涉及一个...

    mysql性能优化之索引优化

    应该针对经常出现在WHERE子句中的列创建索引,尤其是那些用于连接操作或在ORDER BY和GROUP BY中出现的列。主键索引是自动创建的,用于唯一标识每条记录,而唯一索引则确保列中的每个值都是唯一的。除了主键和唯一...

    MySQL中(JOIN/ORDER BY)语句的查询过程及优化方法

    在MySQL查询语句过程和EXPLAIN语句基本概念及其优化中介绍了EXPLAIN语句,并举了一个慢查询例子: 可以看到上述的查询需要检查1万多记录,并且使用了临时表和filesort排序,这样的查询在用户数快速增长后将成为噩梦...

    mysql性能优化.pptx

    - 索引优化SQL:避免全表扫描,尽可能利用索引来加速查询,减少`SELECT`、`JOIN`、`ORDER BY`、`GROUP BY`操作的复杂度。 - 索引维护:定期重建和优化索引,确保其整洁高效。 4. **数据库表结构优化** - **数据...

    MySQL_command.zip_MYSQL

    8. **查询优化**:学习如何编写高效的SQL查询,包括使用JOIN连接多个表,GROUP BY进行分组,HAVING过滤分组后的结果,以及ORDER BY和LIMIT用于排序和限制结果数量。 9. **权限与用户管理**:理解GRANT和REVOKE命令...

    mysql之Linux安装,重点是索引的优化笔记

    ### MySQL之Linux安装与索引优化笔记 #### 一、MySQL简介及Linux版安装 **1. MySQL概述** MySQL是一种关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,目前属于Oracle公司。它是一种开源软件,因其性能...

    mysql order by limit 的一个坑.docx

    解决这个问题的方法是:在 ORDER BY 列中包含一个索引列,例如,我们可以在 ORDER BY 列中加上主键 id,这样可以确保 MySQL 按照正常的排序顺序返回记录。 MySQL 的官方文档中也提到这个问题,原文如此描述: “If...

Global site tag (gtag.js) - Google Analytics