高性能mysql——高性能索引策略
《高性能MySQL》读书笔记
一. 索引的优点
1. 索引可以让服务器快速定位到表的指定位置,大大减少了服务器需要扫描的数量;
2. 最常见的B-Tree索引按照顺序存储数据,可以用来做order by和group by操作帮助服务器避免排序和临时表;
3. 可以将随机I/O变为顺序I/O;
二. 高性能的索引策略
1. 独立的列
索引不能是表达式的一部分,也不能是函数的参数,如,下面这个查询无法使用索引:
SELECT actor_id FROM actor WHERE actor_id+1=5;
2. 前缀索引和索引的选择性
如果需要索引很长的字符串,可以索引开始的部分字符,可以大大节约索引空间从而提高索引效率,但是降低了索引的选择性(不重复的索引值和数据表的记录总数)。为了决定前缀的合适长度,第一种方法是需要找到最常见的值的列表,然后和最常见的前缀列表进行比较。第二种方法是计算完整列的选择性,并使前缀的选择性接近于完整列的选择性:


创建前缀索引:ALTER TABLE sakila.city_demo ADD KEY (city(7));
优点:使索引更小更快的有效办法;
缺点:无法使用前缀索引做覆盖扫描,无法使用前缀索引做ORDER BY,GROUP BY;
3. 多列索引
在多个列上建立单独的索引大部分情况下不能提高mysql的查询性能,在老版本的mysql中,只能使用其中某一个单列索引,然而这种情况下没有哪一个单例索引是非常有效的。MySQL5.0和更新版本中引入了“索引合并”,能够同时使用多个单例索引进行扫描,并将结果进行合并,包括:OR条件的联合(union),AND条件的相交(intersection),组合这两种情况的联合及相交。

索引合并策略有时候是一种优化的结果,但实际上说明了表上的索引建的很糟糕:
- 当出现服务器对多个索引做相交操作时(通常有多个AND条件),通常意味着需要一个包含所有相关列的多列索引;
- 当服务器需要对多个索引做联合操作时(通常有多个OR条件),通常需要耗费大量的CPU资源和内存资源在算法的缓存,排序和合并操作上。
- 优化器不会把这些计算到“查询成本”中,优化器只关心随机页面读取,使得查询的成本被低估导致该执行计划还不如走全表扫描。
如果在explain中看到索引合并,应该好好检查一下查询和表的结构,看是不是已经是最优的,也可以通过参数optimizer_switch来关闭索引合并功能。
4. 选择合适的索引顺序
当不需要考虑排序和分组时,将选择性最高的列放在前面通常是很好的,这是后索引的作用只是用于优化where条件的查询,对于在where子句中使用了索引部分前缀列的查询来说选择性也更高。然而,性能不只是依赖于所有索引列的选择性(整体基数),也和查询条件的具体值有关(值得分布)。
5. 聚簇索引(数据行存放在索引的叶子页)
优点:
- 把相关的数据保存在一起减少磁盘IO;
- 聚簇索引将索引和数据页保存在同一个B-Tree中,数据访问更快,不用回表查询;
- 使用覆盖索引扫描得查询可以直接使用叶结点中得主键值;
缺点:
- 如果数据全都放在内存中,则访问顺序没那么重要了,聚簇索引就没优势;
- 插入数据的速度依赖于插入顺序,按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式,如果不按主键顺序加载数据,那么在加载完成后最好使用optimize table命令重新组织一下表;
- 更新聚簇索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置;
- 基于聚簇索引列的表在插入新行,或者主键被更新导致需要移动行的时候,可能会面临“页分裂”的问题,页分裂会导致表占用更多的磁盘空间;
- 聚簇索引可能会导致全表扫描变慢,尤其是行比较稀疏,或者由于分页导致数据存储不连续的时候;
- 二级索引(非聚簇)可能比想象中的更大,因为在二级索引的叶子节点包含了引用行的主键列;且需要两次索引查找;
InnoDB和MyISAM的数据分布对比:
MyISAM的数据分布:按照数据插入顺序存储在磁盘上,叶子节点存储的是“行号”,这种分布方式很容易创建索引,且二级索引和主键索引的存储方式相同;
InnoDB的数据分布:聚簇索引的每一个叶子节点都包含了主键值,事务ID,用于事务和MVCC的回滚指针以及所有剩余列,二级索引和聚簇索引很不同,叶子节点存储的是主键值,这种策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。
6. 覆盖索引(一个索引包含所有要查询的字段的值,查询只需扫描索引而无需回表)
优点:
- 索引的条目通常要小于数据行的大小,如果只需要读索引,MySQL就会极大地减少数据访问量;
- 索引是按列值顺序存储的(至少在一个单页内),所以对于I/O密集型的范围查询回比从磁盘读取每一行数据的I/O要少的多;
- 一些存储引擎如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此访问数据需要一次系统调用;
- 由于InnoDB的聚簇索引,覆盖索引对InnDB表特别有用,InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,可以避免对主键索引的二级查询;
7. 使用索引扫描来做排序
MySQL有两种方式可以生成有序的结果:通过排序操作或者按照索引顺序扫描,如果explain出来的type列的值为index,则说明mysql使用了索引扫描来做排序;
扫描索引本身虽然很快,但如果索引不能覆盖查询所需的全部列,就不得不每扫描一条索引记录就回表查询一次对应得行,这基本都是随机I/O操作,所以按索引顺序读取数据得速度通常要比顺序地全表扫描还要慢;
只有当索引得列顺序和order by子句得顺序完全一致,并且所有列得排序方向都一样时,MySQL才能够使用索引来对结果做排序;如果查询需要关联多张表,则只有当order by子句引用得字段全部为第一个表时才能使用索引做排序。
8. 压缩(前缀压缩)索引
MyISAM压缩每个索引块得方法是,先完全保存索引块中得第一个值,然后将其他值和第一个值进行比较得到相同前缀得字节数和剩余得不同后缀部分,把这部分存储起来即可。
优点:使用得空间减小;
缺点:有些操作可能变慢,MyISAM查找时无法在索引块使用二分查找而只能从头开始扫描;
9. 冗余和重复索引
MySQL允许在相同列上创建多个索引,并需要单独维护重复索引,并且优化器在优化查询得时候也需要逐个地进行考虑,影响性能;重复索引是指在相同得列上按照相同得顺序创建相同类型得索引(如创建主键,加上唯一限制后,又加索引会创建三个重复二等索引),应该避免,并及时删除;冗余索引不等于重复索引,如创建了索引(A,B)后又创建了索引(A),A是冗余索引因为它是前一个索引得前缀索引,但如果再创建索引(B,A)或者(B)则不是冗余索引;
解决冗余和重复索引得方法很简单,删除这些索引就可以了,但是要先找出这些索引。可以通过写一些复杂得访问INFORMATION_SCHEMA表得查询来找,或者使用common_schema中得一些视图来定位。
10. 未使用得索引
定位未使用得索引:在Percona Server或MariaDB中先打开userstates服务器变量(默认是关闭的),然后让服务器运行一段时间再通过查询INFORMATION_SCHEMA.INDEX_STATISTICS就能查到每个索引得使用频率;
11. 索引和锁
索引可以让查询锁定更少得行,虽然InnoDB行锁得效率很高,内存使用也很少,但是锁定行的时候仍然会带来额外开销,其次,锁定超过需要的行会增加锁争用并减少并发性。
高性能mysql——高性能索引策略的更多相关文章
- 高性能Mysql笔记 — 索引
index优化 对于频繁作为查询条件的字段使用索引 注意索引字段类型的隐式转换,数据库类型和应用类型要一致 索引的种类 唯一索引,成为索引的列不能重复 单列索引,一个索引只包含一列 单列前缀索引,有些 ...
- 高性能MySQL(一)——索引
一.mysql索引分类 单值索引:一个索引只包含单个列,一个表可以有多个单列索引 唯一索引:索引列的值必须唯一,但允许有空值 复合索引:一个索引包含多个列 基本语法: 创建:1.CREATE [UNI ...
- 高性能MySQL之索引深入原理分析
一.背景 我们工作中经常打交道的就是索引,那么到底什么是索引呢?例如,当一个SQL查询比较慢的时候,你可能会说给“某个字段加个索引吧”之类的解决方案. 总的来说索引的出现其实就是为了提高数据查询的效率 ...
- mysql高性能索引策略
转载说明:http://www.nyankosama.com/2014/12/19/high-performance-index/ 1. 引言 随着互联网时代地到来,各种各样的基于互联网的应用和服务进 ...
- MySQL建立高性能索引策略
索引永远是最好的查询解决方案嘛? 索引并不总是最好的工具.总的来说,只有当索引帮助存储引擎快速查找到记录带来的好处大于其带来的额外工作(比如插入操作后索引的维护)时,索引才是高效的. 对于非常小的表: ...
- mysql索引性能验证,高性能的索引策略
索引性能验证 1.无索引列的查询 在where条件中查询没有添加索引的列,性能会比较差.我们可以先在sqlyog中打开表t_user的数据,然后复制一个名字出来进行查询. /*无索引列的查询,索引不会 ...
- MySQL索引背后的之使用策略及优化(高性能索引策略)
为了讨论索引策略,需要一个数据量不算小的数据库作为示例.本文选用MySQL官方文档中提供的示例数据库之一:employees.这个数据库关系复杂度适中,且数据量较大.下图是这个数据库的E-R关系图(引 ...
- 高性能MySQL笔记 第5章 创建高性能的索引
索引(index),在MySQL中也被叫做键(key),是存储引擎用于快速找到记录的一种数据结构.索引优化是对查询性能优化最有效的手段. 5.1 索引基础 索引的类型 索引是在存储引擎层而 ...
- 高性能mysql:创建高性能的索引
本文系阅读<高性能MySQL>,Baron Schwartz等著一书中第五章 创建高性能的索引的笔记,索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键,尤其是当表 ...
随机推荐
- uwsgi启动报错 chdir(): No such file or directory [core/uwsgi.c line 2591]
今天在使用 uwsgi --ini uwsgi.ini 命令时总说找不到我的项目路径,可是我的路径是绝对没有问题的 解决方法: 把你的uwgis.ini文件里的全部注释删除,再运行uwsgi 启动成功 ...
- 使用three.js创建大小不随着场景变化的文字
使用three.js创建大小不随着场景变化的文字,需要以下两步: 1.将文字绘制到画布上. 2.创建着色器材质,把文字放到三维场景中. 优点: 1.跟用html实现文字相比,这些文字可以被模型遮挡,更 ...
- SpringMVC参数绑定学习总结【前后端数据参数传递】
目录 1. 绑定机制 2. 支持的数据类型 3. 参数请求中文乱码解决 4.自定义类型转换器 5.最后参数绑定学习小结 SpringMVC作为Controller层(等价servlet和struts中 ...
- 《手把手教你》系列练习篇之6-python+ selenium自动化测试(详细教程)
1. 简介 前面文章我们了解了如何获取元素的text属性值,和判断元素是否显示在页面(is_displayed()方法),本文我们来学习下,判断一个控件是否被选中状态. 2. 验证控件是否被选中 还是 ...
- word is too tall: try to use less letters, smaller font or bigger background 报错 java程序 验证码不显示
验证码不现实问题爆发在测试站,还好只是个测试站,有时间让我慢慢研究此问题. 具体的情况是这样的: 下午三点多,突然测试人员跟我说,测试站后台的验证码不现实了,也就无法登陆了 通过询问,是中午吃饭前还是 ...
- 《Windows内核安全与驱动开发》 3.2 内存与链表
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.2 内存与链表 1. 尝试生成一个链表头并将其初始化. 2. 尝试向内存 ...
- (一)sync分析之为啥el-dialog中的visible需要使用.sync
首先,笔者在使用element-ui 中的dialog组件时,发现visible属性在使用时需要添加.sync才生效,心中好奇,所以研究一下原理 我们先自己创建一个dialog组件,如下 当我们点击关 ...
- 区块链学习笔记:D02 区块链的技术发展历史和趋势
对于区块链的技术发展历史,其实在我的印象中也就对比特币有所了解,也听过什么火币之类的玩意,但是具体是什么.怎么运作的就不清楚了... 这次的内容首先是讲解了区块链的技术演进,一张图一目了然,虽然里面涉 ...
- 索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会!
前言 Hello我又来了,快年底了,作为一个有抱负的码农,我想给自己攒一个年终总结.自上上篇写了手动搭建Redis集群和MySQL主从同步(非Docker)和上篇写了动手实现MySQL读写分离and故 ...
- java.security.NoSuchProviderException: no such provider: BC 的问题解决
第一种方式 1.修改以下两个文件 %JDK_Home%\jre\lib\security\java.security %JRE_Home%\jre\lib\security\java.security ...