高性能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等著一书中第五章 创建高性能的索引的笔记,索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键,尤其是当表 ...
随机推荐
- vue 解决跨域
先上报错 以表尊重 在vue中 找到 config文件夹中的 index.js文件 配置更改如下 proxyTable: { '/api': { target: 'http://47.240.11. ...
- selenium(java)浏览器多窗口切换处理
要在多个窗口直接切换,首先获取每个窗口的唯一标示符(句柄),通过窗口属性可以获取所有打开窗口的标示符,以集合的形式返回:以下示例: Set<String> winHandels ...
- 经典sql面试题(学生表_课程表_成绩表_教师表)
转载:https://www.cnblogs.com/qixuejia/p/3637735.html 表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cna ...
- 浅谈集群版Redis和Gossip协议
昨天的文章写了关于分布式系统中一致性哈希算法的问题,文末提了一下Redis-Cluster对于一致性哈希算法的实现方案,今天来看一下Redis-Cluster和其中的重要概念Gossip协议. 1.R ...
- 手机端web(iPad)页面自适应js
有关编写手机页面(ipad页面)自适应的方法有很多,比如:bootstrap,rem等等.下面分享给大家一个js控制viewPort视区自适应缩放的方法(我给它命名为phone.js): 将phone ...
- JS获取当前完整的url地址以及参数的方法
javascript 获取当前 URL 参数的两种方法: //返回的是字符串形式的参数,例如:class_id=3&id=2& function getUrlArgStr(){ var ...
- 文件上传之靶场upload-labs (1-10)
第一关 sj 绕过 源码如下: lasIndexOf是返回函数最后一次出现的地方(从右到左) substring是用来截取函数的 indexOf是返回 表示从.出现的地方开始截取并判断是否在允许的字符 ...
- 华为云BigData Pro解读: 鲲鹏云容器助力大数据破茧成蝶
华为云鲲鹏云容器 见证BigData Pro蝶变之旅大数据之路顺应人类科技的进步而诞生,一直顺风顺水,不到20年时间,已渗透到社会生产和人们生活的方方面面,.然而,伴随着信息量的指数级增长,大数据也开 ...
- P2910 [USACO08OPEN]寻宝之路Clear And Present Danger |Floyd
题目描述 农夫约翰正驾驶一条小艇在牛勒比海上航行. 海上有N(1≤N≤100)个岛屿,用1到N编号.约翰从1号小岛出发,最后到达N号小岛. 一张藏宝图上说,如果他的路程上经过的小岛依次出现了Ai,A2 ...
- C# 设置、删除、读取Word文档背景——基于Spire.Cloud.Word
Spire.Cloud.Word.Sdk提供了接口SetBackgroudColor().SetBackgroudImage().DeleteBackground().GetBackgroudColo ...