《高性能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——高性能索引策略的更多相关文章

  1. 高性能Mysql笔记 — 索引

    index优化 对于频繁作为查询条件的字段使用索引 注意索引字段类型的隐式转换,数据库类型和应用类型要一致 索引的种类 唯一索引,成为索引的列不能重复 单列索引,一个索引只包含一列 单列前缀索引,有些 ...

  2. 高性能MySQL(一)——索引

    一.mysql索引分类 单值索引:一个索引只包含单个列,一个表可以有多个单列索引 唯一索引:索引列的值必须唯一,但允许有空值 复合索引:一个索引包含多个列 基本语法: 创建:1.CREATE [UNI ...

  3. 高性能MySQL之索引深入原理分析

    一.背景 我们工作中经常打交道的就是索引,那么到底什么是索引呢?例如,当一个SQL查询比较慢的时候,你可能会说给“某个字段加个索引吧”之类的解决方案. 总的来说索引的出现其实就是为了提高数据查询的效率 ...

  4. mysql高性能索引策略

    转载说明:http://www.nyankosama.com/2014/12/19/high-performance-index/ 1. 引言 随着互联网时代地到来,各种各样的基于互联网的应用和服务进 ...

  5. MySQL建立高性能索引策略

    索引永远是最好的查询解决方案嘛? 索引并不总是最好的工具.总的来说,只有当索引帮助存储引擎快速查找到记录带来的好处大于其带来的额外工作(比如插入操作后索引的维护)时,索引才是高效的. 对于非常小的表: ...

  6. mysql索引性能验证,高性能的索引策略

    索引性能验证 1.无索引列的查询 在where条件中查询没有添加索引的列,性能会比较差.我们可以先在sqlyog中打开表t_user的数据,然后复制一个名字出来进行查询. /*无索引列的查询,索引不会 ...

  7. MySQL索引背后的之使用策略及优化(高性能索引策略)

    为了讨论索引策略,需要一个数据量不算小的数据库作为示例.本文选用MySQL官方文档中提供的示例数据库之一:employees.这个数据库关系复杂度适中,且数据量较大.下图是这个数据库的E-R关系图(引 ...

  8. 高性能MySQL笔记 第5章 创建高性能的索引

    索引(index),在MySQL中也被叫做键(key),是存储引擎用于快速找到记录的一种数据结构.索引优化是对查询性能优化最有效的手段.   5.1 索引基础   索引的类型   索引是在存储引擎层而 ...

  9. 高性能mysql:创建高性能的索引

    本文系阅读<高性能MySQL>,Baron Schwartz等著一书中第五章 创建高性能的索引的笔记,索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键,尤其是当表 ...

随机推荐

  1. [ch03-01] 均方差损失函数

    系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 3.1 均方差函数 MSE - Mean Square ...

  2. 基于loghub的消息消费延迟监控

    我们可以把loghub当作一个消息中间件来使用.如果能知道当前的消费进度,自然好了,否则消费情况一无所知,总是有点慌! loghub消费分两种情况,一是普通消费,二是消费组消费: 消费组消费,logh ...

  3. Reactor和Proactor模型

    背景 前面介绍了I/O多路复用模型,那有了I/O复用,有了epoll已经可以使服务器并发几十万连接的同时,还能维持比较高的TPS,难道还不够吗?比如现在在使用epoll的时候一般都是起个任务,不断的去 ...

  4. 【NHOI2018】找素数

    [题目描述] 素数又称质数,是指一个大于 1 的正整数,如果除了 1 和它本身以外,不能再被其它的数整除,例如:2.3.5.97 等都是素数.2 是最小的素数. 现在,给你 n 个数字,请你从中选取一 ...

  5. 搭建nextcloud私有云存储网盘

    简介: 搭建个人云存储一般会想到ownCloud,堪称是自建云存储服务的经典.而Nextcloud是ownCloud原开发团队打造的号称是“下一代”存储. 真正试用过后就由衷地赞同这个Nextclou ...

  6. 伪共享 FalseSharing (CacheLine,MESI) 浅析以及Java里的解决方案

    起因 在阅读百度的发号器 uid-generator 源码的过程中,发现了一段很奇怪的代码: /** * Represents a padded {@link AtomicLong} to preve ...

  7. 虚拟机中linux操作系统raid5(5块磁盘,3块做raid,2块做备份)配置流程及损坏磁盘的移除

    1.打开所要用的虚拟机,点击编辑虚拟机设置,点击硬盘,添加 2.一直点击下一步不做修改,直到最后完成 3.按照以上步骤添加5块磁盘 4.点击开启虚拟机,输入用户名root密码登录进去 5.进入虚拟机后 ...

  8. python BeautifulSoup4 获取 script 节点问题

    在爬取12306站点名时发现,BeautifulSoup检索不到station_version的节点 因为script标签在</html>之外,如果用‘lxml’解析器会忽略这一部分,而使 ...

  9. mq解决分布式事物问题

    今天只看看原理,下一节看项目怎么集成mq进行解决分布式事物. 1.什么情况下会使用到分布式事物? 举例说明:现有一个支付系统,因为项目使用的是微服务框架,有订单模块和支付模块两个模块.生产者进行订单的 ...

  10. react-native 信鸽推送集成

    目录 一. git链接: react-native-xinge-push 1.1 安装 1.2. link 二. android配置 2.1. android/settings.gradle 2.2. ...