MYSQL查询优化:使用索引
索引是提高查询速度的最重要的工具。当然还有其它的一些技术可供使用,但是一 般来说引起最大性能差异的都是索引的正确使用。在MySQL邮件列表中,人们经常询问那些让查询运行得更快的方法。在大多数情况下,我们应该怀疑数据表上 有没有索引,并且通常在添加索引之后立即解决了问题。当然,并不总是这样简单 就可以解决问题的,因为优化技术本来就并非总是简单的。然而,如果没有使用索引,在很多情况下,你试图使用其它的方法来提高性能都是在浪费时间。首先使用 索引来获取最大的性能提高,接着再看其它的技术是否有用。
这一部分讲述了索引是什么以及索引是怎么样提高查询性能的。它还讨论了在某些环境中索引可能降低性能,并为你明智地选择数据表的索引提供了一些指导方 针。在下一部分中我们将讨论MySQL查询优化器,它试图找到执行查询的效率最高的方法。了解一些优化器的知识,作为对如何建立索引的补充,对我们是有好 处的,因为这样你才能更好地利用自己所建立的索引。某些编写查询的方法实际上让索引不起作用,在一般情况下你应该避免这种情形的发生。
索引的优点
让我们开始了解索引是如何工作的,首先有一个不带索引的数据表。不带索引的表仅仅是一个无序的数据行集合。例如,图1显示的ad表就是不带索引的表,因此如果需要查找某个特定的公司,就必须检查表中的每个数据行看它是否与目标值相匹配。这会导致一次完全的数据表扫描,这个过程会很慢,如果这个表很大,但是只包含少量的符合条件的记录,那么效率会非常低。
![]() 图1:无索引的ad表 |
图2是同样的一张数据表,但是增加了对ad表的company_num数据列的索引。这个索引包含了ad表中的每个数据行的条目,但是索引的条目是按照
company_num值排序的。现在,我们不是逐行查看以搜寻匹配的数据项,而是使用索引。假设我们查找公司13的所有数据行。我们开始扫描索引并找到
了该公司的三个值。接着我们碰到了公司14的索引值,它比我们正在搜寻的值大。索引值是排过序的,因此当我们读取了包含14的索引记录的时候,我们就知道
再也不会有更多的匹配记录,可以结束查询操作了。因此使用索引获得的功效是:我们找到了匹配的数据行在哪儿终止,并能够忽略其它的数据行。另一个功效来自使用定位算法查找第一条匹配的条目,而不需要从索引头开始执行线性扫描(例如,二分搜索就比线性扫描要快一些)。通过使用这种方法,我们可以快速地定位第一个匹配的值,节省了大量的搜索时间。数据库使用了多种技术来快速地定位索引值,但是在本文中我们不关心这些技术。重点是它们能够实现,并且索引是个好东西。
![]() 图2:索引后的ad表 |
你可能要问,我们为什么不对数据行进行排序从而省掉索引?这样不是也能实现同样的搜索速度的改善吗?是的,如果表只有一个索引,这样做也可能达到相同的
效果。但是你可能添加第二个索引,那么就无法一次使用两种不同方法对数据行进行排序了(例如,你可能希望在顾客名称上建立一个索引,在顾客ID号或电话号
码上建立另外一个索引)。把与数据行相分离的条目作为索引解决了这个问题,允许我们创建多个索引。此外,索引中的行一般也比数据行短一些。当你插入或删除
新的值的时候,移动较短的索引值比移动较长数据行的排序次序更加容易。
不同的MySQL存储引擎的索引实现的具体细节信息是不同的。
例如,对于MyISAM数据表,该表的数据行保存在一个数据文件中,索引值保存在索引文件中。一个数据表上可能有多个索引,但是它们都被存储在同一个索引文件中。索引文件中的每个索引都包含一个排序的键记录(它用于快速地访问数据文件)数组。
与此形成对照的是,BDB和InnoDB存储引擎没有使用这种方法来分离数据行和索引值,尽管它们也把索引作为排序后的值集合进行操作。在默认情况下,BDB引擎使用单个文件存储数据和索引值。
InnoDB使用单个数据表空间(tablespace),在表空间中管理所有InnoDB表的数据和索引存储。我们可以把InnoDB配置为每个表都在自己的表空间中创建,但是即使是这样,数据表的数据和索引也存储在同一个表空间文件中。
前面的讨论描述了单个表查询环境下的索引的优点,在这种情况下,通过减少对整个表的扫描,使用索引明显地提高了搜索的速度。当你运行涉及多表联结
(jion)查询的时候,索引的价值就更高了。在单表查询中,你需要在每个数据列上检查的值的数量是表中数据行的数量。在多表查询中,这个数量可能大幅度
上升,因为这个数量是这些表中数据行的数量所产生的。
假设你拥有三个未索引的表t1、t2和t3,每个表都分别包含数据列i1、i2和i3,并且每个表都包含了1000条数据行,其序号从1到1000。查找某些值匹配的数据行组合的查询可能如下所示:
| SELECT t1.i1, t2.i2, t3.i3 FROM t1, t2, t3 WHERE t1.i1 = t2.i2 AND t2.i1 = t3.i3; |
这个查询的结果应该是1000行,每个数据行包含三个相等的值。如果在没有索引的情况下处理这个查询,那么如果我们不对这些表进行全部地扫描,我们是没
有办法知道哪些数据行含有哪些值的。因此你必须尝试所有的组合来查找符合WHERE条件的记录。可能的组合的数量是1000 x 1000 x
1000(10亿!),它是匹配记录的数量的一百万倍。这就浪费了大量的工作。这个例子显示,如果没有使用索引,随着表的记录不断增长,处理这些表的联结
所花费的时间增长得更快,导致性能很差。我们可以通过索引这些数据表来显著地提高速度,因为索引让查询采用如下所示的方式来处理:
1.选择表t1中的第一行并查看该数据行的值。
2.使用表t2上的索引,直接定位到与t1的值匹配的数据行。类似地,使用表t3上的索引,直接定位到与表t2的值匹配的数据行。
3.处理表t1的下一行并重复前面的过程。执行这样的操作直到t1中的所有数据行都被检查过。
在这种情况下,我们仍然对表t1执行了完整的扫描,但是我们可以在t2和t3上执行索引查找,从这些表中直接地获取数据行。理论上采用这种方式运行上面
的查询会快一百万倍。当然这个例子是为了得出结论来人为建立的。然而,它解决的问题却是现实的,给没有索引的表添加索引通常会获得惊人的性能提高。
MySQL有几种使用索引的方式:
· 如上所述,索引被用于提高WHERE条件的数据行匹配或者执行联结操作时匹配其它表的数据行的搜索速度。
· 对于使用了MIN()或MAX()函数的查询,索引数据列中最小或最大值可以很快地找到,不用检查每个数据行。
· MySQL利用索引来快速地执行ORDER BY和GROUP BY语句的排序和分组操作。
·
有时候MySQL会利用索引来读取查询得到的所有信息。假设你选择了MyISAM表中的被索引的数值列,那么就不需要从该数据表中选择其它的数据列。在这
种情况下,MySQL从索引文件中读取索引值,它所得到的值与读取数据文件得到的值是相同的。没有必要两次读取相同的值,因此没有必要考虑数据文件。
索引创建规则:
1、表的主键、外键必须有索引;
2、数据量超过300的表应该有索引;
3、经常与其他表进行连接的表,在连接字段上应该建立索引;
4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
5、索引应该建在选择性高的字段上;
6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
A、正确选择复合索引中的主列字段,一般是选择性较好的字段;
B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;
C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;
D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;
E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;
8、频繁进行数据操作的表,不要建立太多的索引;
9、删除无用的索引,避免对执行计划造成负面影响;
以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。
因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。
另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。
转载:http://dev.yesky.com/381/2108381.shtml?412
MYSQL查询优化:使用索引的更多相关文章
- Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析
Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析 Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析1 存 ...
- mysql七:索引原理与慢查询优化(待完整)
一.介绍 索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构.索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要. 索引优化应该是对查询性能优 ...
- 0x08 MySQL 超详细-索引原理&慢查询优化【转-多图】(重点)
Content From——Egon's Blog http://www.cnblogs.com/linhaifeng/articles/7274563.html#top 0x01 介绍 为何要有索引 ...
- MySQL基础、索引、查询优化等考察点
MySQL基础 MySQL数据类型 整数类型 TINYINT. SMALLINT. MEDIUMINT. INT. BIGINT 属性:UNSIGNED 长度:可以为整数类型指定宽度,例如:INT(1 ...
- Mysql基础(六):索引、数据库备份、锁和事务、慢查询优化、索引命中相关
目录 数据库05 /索引.数据库备份.锁和事务.慢查询优化.索引命中相关 1. 什么是索引 2. 索引的原理 3. 索引的数据结构(聚集索引.辅助索引) 4. 索引操作 5. 索引的两大类型hash与 ...
- MySQL查询优化之explain的深入解析
在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...
- 1025WHERE执行顺序以及MySQL查询优化器
转自http://blog.csdn.net/zhanyan_x/article/details/25294539 -- WHERE执行顺序-- 过滤比较多的放在前面,然后更加容易匹配,从左到右进行执 ...
- MySQL查询优化:查询慢原因和解决技巧
在开发的朋友特别是和mysql有接触的朋友会碰到有时mysql查询很慢,当然我指的是大数据量百万千万级了,不是几十条了,下面我们来看看解决查询慢的办法. MySQL查询优化:查询慢原因和解决方法 会经 ...
- mysql查询优化器为什么可能会选择错误的执行计划
有可能导致mysql优化器选择错误的执行计划的原因如下: A:统计信息不准确,mysql依赖存储引擎为其提供的统计信息来评估成本,然而有的存储引擎提供的信息是准确的,有的引擎提供的可能就偏差很大,如: ...
随机推荐
- ASP.NET自定义错误页并返回正确的500、404状态码
在项目中,我们常常需要自定义错误页面,但往往返回的状态码都变成了200,对SEO很不友好.我尝试过在百度上寻找解决方案,但找到的资料中说的方法都试过了,发现都是无法返回正确的状态码的. 最后,只好自已 ...
- 自定义延时关闭弹窗,替代MesssageBox
1,新建一个窗体MessageForm,在里面加一个label控件和timer 2,代码如下: public partial class MessageForm : Form { int t; str ...
- 全球第一开源ERP Odoo操作手册 数据库简介
1.3 数据库简介 每一个独立核算的企业都有一套相互关联的账簿体系, 把这一套完整的账簿体系建立在计算机系统中就称为一个数据库. 一般一个企业只用一个数据库. 如果企业有几个下属的独立核算的实体,也可 ...
- [宁波集训]0827Day1
1.\(CF771D\ Bear\ and\ Company\)(原题,比赛时改为多组数据) 一道毒瘤\(dp\)题,\(dp[i][j][k][0/1]\)表示有\(i\)个\(V\),有\(j\) ...
- Spring 全局异常处理
[参考文章]:Spring全局异常处理的三种方式 [参考文章]:Spring Boot 系列(八)@ControllerAdvice 拦截异常并统一处理 [参考文章]:@ControllerAdvic ...
- Testing - 软件测试知识梳理 - 软件可靠性测试
软件可靠性的基本概念 错误,缺陷,故障和失效 错误:指的是软件在生命周期中各个阶段的状态和行为与人们的期待不一致的偏差,不单单是软件系统本身,中间产品的偏差也算是软件错误 缺陷:指的是软件中一切不好的 ...
- [Leetcode]123.买卖股票的最佳时机3
[原题链接][https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/] 分析:动态规划+二分法.以第i天为分界线,计 ...
- Vue, React, AngularJS, and Angular2. 我们对流行JavaScript框架们的选择
2017-08-04 前端大全 (点击上方公众号,可快速关注) 英文:ANTONI ZOLCIAK 译文:众成翻译 www.zcfy.cc/article/vue-react-angularjs-a ...
- WIN10安装scrapy/channels等不成功的解决方式
问题 在Win10机器上,不管是安装scrapy还是channels,都需要安装一个包,叫做twisted.正是这个twisted,导致出现一系列的奇葩错误,让我一度以为我的Pycharm坏了,还改了 ...
- CDH 版本子节点启动问题
今天下午整整为了启动一个节点瞎忙活一下午,惨痛的教训还是记录下来吧,毕竟付出了代价.事情原委,一个同事在一台机器上占用了大量内存训练CTR点击率模型,而这台机器上部署了分布式Hadoop的一个data ...

