/* * -------------------------------------------------------- * 高性能MySQL-3rd-Baron Schwartz-笔记 * 第五章 建立高性能的索引 */ --------------------------------------------------------
5.1 索引基础
html
简单讲,索引就是书籍后面的“索引”-Index,帮助咱们找到特定主题、词语,而后告诉咱们具体对应的页码。在MySQL中存储引擎用相似的方法使用索引,先在索引中找到对应的值,而后根据匹配的索引记录找到对应的数据行。java
简单例子: select name from actor where actor_id=5; 前提:actor_id 列上建有索引。MySQL 将使用在该列上建立的索引找到 actor_id 为 5 的行,按值在索引上查找,而后返回包含该值(5)的数据行。mysql
像上面的例子,通常可能直接被认为 actor 表以 actor_id 一个列为索引,但正如大多数人作的那样,一个表的索引可能还会包含一个以上的列(多个列)的值。若是是多个列,那么顺序很重要,由于MySQL只能高效利用 最左前缀列。另外,建立一个包含两个列的索引,和建立两个只包含一个列的索引是大不相同的,将来解释。sql
不管多么复杂的ORM工具,在精妙和复杂的索引面前都是浮云!服务器
索引有不少类型,索引在存储引擎层实现,不在服务器层,所以不一样存储引擎、不一样索引类型的底层实现都不相同。基本类型包括B-Tree索引、哈希索引、空间数据索引(R-Tree)、全文索引等。
工具
==================== B-Tree索引 ==============
性能
上面的表中,姓(last_name)、名(first_name)、出生日期(dob)为索引(key),图上为这三个列组成的索引的数据组织形式,其中 last_name (姓)是最左前缀,参考连接《最左前缀原则(博文)》优化
B-Tree索引适用于全值匹配(索引中全部列匹配,Allen、Cuba、1960-01-01)、匹配最左前缀(索引的前缀列,只使用索引第一列,姓 Allen)、匹配列前缀(索引列的前缀,姓列前缀,查 All开头的姓)、匹配范围值(查找 A字母~B字母开头的姓)、精确匹配某一列并范围匹配另一列(姓列精确匹配=Allen,名称列范围,以K字母开头的名)、只访问索引的查询(不访问数据行,叫“覆盖索引”,将来解释)。搜索引擎
B-Tree以上查找原则,也使用于 ORDER BY 排序字段,能查找就能排序。spa
B-Tree有些傻乎乎,像人同样执拗得狠!不能跳过最左前缀(last_name),只查知足名字和生日的不行;也不能跳过中间列,只查知足姓和生日的不行;若是中间列有范围查询,则居其右边的列优化用不上,例如:WHERE last_name='Smith' AND first_name LIKE 'J%' dob='1976-12-23',dob的优化用不上,由于 first_name 是个范围查询。
由上能够看出 B-Tree索引列的顺序多么多么的重要,在优化时,须要建立相同的多个列但顺序不一样的索引,来知足不一样的需求,如:key1(last_name, first_name, dob),key1(first_name, last_name, dob), key1( dob, first_name, last_name)
==================== 哈希索引 ==============
哈希索引,仅用于精确匹配,仅存在于Memory引擎,每行数据都计算一个哈希码(hash code),MySQL接收查询命令后,如:select last_name from People where first_name='Peter' ,先计算 Peter 的哈希值,而后用该哈希值找到记录数据行的指针,经过指针找到数据行,而后判断找到的数据是否为Peter,若是是返回数据。
哈希索引,特色结构紧凑,速度快。
伪哈希索引,由于哈希索引只在 Memory中存在,因此能够参考书中自行在其余引擎中建立伪哈希索引,效果不错,但注意哈希值冲突的解决。
==================== 空间数据索引(R-Tree) ==============
MyISAM支持空间数据索引,能够用做地理数据存储。但MySQL作得很差,不多使用。
==================== 全文索引 ==============
全文索引,查找的是文本中的关键词,而不是直接比较索引中的值,与其余索引彻底不一样,不是简单的 WHERE 匹配,而更像搜索引擎作的事情,适用于 MATCH AGAINST 操做。
全文索引,详细见第七章。
===========================================================
5.2 索引优势
索引优势,大大减小了服务器须要扫描的数据量(快速定位);
索引优势,能够帮助服务器避免排序和临时表(顺序存储,便于ORDER BY、GROUP BY);
索引优势,将随机I/O,变为顺序I/O。
索引辩证法,小表,全表扫描更高效;中大表,索引高效;超大表,索引代价高,可使用分区技术,见第7章。
===========================================================
5.3 高性能索引策略
1)将索引列要独立,放在比较符号的一侧,例如 select * from actor where actor_id + 1 = 5; 应写为 select * from actor where actor_id = 4;
2)前缀索引,通常对BLOB、TEXT、很长的VARCHAR使用,须要保证索引的选择性要高,就是索引的值的数量和记录的总数尽可能持平,通常的自增id做为索引基本上选择性=1,不会重复。使用前缀索引要先预估选择性的值,书中有实例。
3)多列索引,在多个列上单独创建索引多数状况下不能提升效率,特别对于AND、OR操做,OR操做更浪费。
4)选择合适的索引列顺序,将选择性最高的列放最左,但只是经验作法。
5) 聚簇索引
6)覆盖索引
7)使用索引扫描来作排序!(很重要!!!)
MySQL经过两种方式生成有序结果:经过排序操做,或,按索引顺序扫描。当 Explain的结果中 type 为 index,就说明MySQL用了索引扫描来作排序了!
扫描索引是很快了的,但若是索引没有能覆盖查询中所需的所有列,那就不得不每扫描一条索引记录就回表查询一次对应的行(自问:为何?:-))这基本就是随机I/O了,慢,慢!
设计时,必定要注意,若是有一条索引(可能多个列),既能知足查找,又能知足排序,那就行了。
参考资料:mysql explain