索引类型:
索引是在存储引擎层而不是服务器层实现的,所以不同存储引擎的索引工作方式不一样,也不是所有存储引擎都支持所有类型的索引,及时多个存储引擎支持同一种类型,底层实现也可能不同
- B-Tree索引
- 哈希索引
- 空间数据索引
- 全文索引 等
索引策略:
- 独立的列
如果查询中的列不是独立的,MYSQL就不会使用索引。“独立的列是指索引列不能是表达式的一部分,也不能是函数的参数”
- 前缀索引和索引选择性
有时候需要索引很长的字符列,会让索引变得大且慢,一个策略是通过模拟哈希索引,还可以通过索引开始的部分字符,这样可以大大节约索引空间,提高索引效率,但会降低索引的选择性(索引选择性是指不重复的索引值,即,基数和数据表的记录总数(#T)的比值,范围从1/#T到1之间。索引选择性越高,查询效率越高,唯一索引的选择性是1,是最好的索引选择性,性能也是最好的)
- 多列索引
索引可以包含一个或多个列的值。如果索引包含多个列,那么列的顺序十分重要,因为MysSQL只能高效地使用索引的最左前缀列。创建一个包含两个列的索引,和创建两个只包含一列的索引是大不相同的。
索引对多个值排序的依据是CREATE TABLE 语句中定义索引时列的顺序。
- 选择合适的索引列顺序
当不需要考虑排序和分组时,将选择性最高的列放在前面通常是很好的。这时候索引的作用只是用于优化WHERE条件的查找。然而,性能不只是依赖于所有索引列的选择性,也和查询条件的具体值有关,也就是和值的分布有关。可能需要根据那些运行频率最高的查询来调整索引列的顺序,让这种情况下索引的选择性最高。
- 聚簇索引
聚簇索引并不是一种单独的索引类型,而是一个种数据存储方式。聚簇表示数据行和相邻的键值紧凑地存储在一起。因为无法同时把数据行存放在两个不同地地方,所以一个表只能有一个聚簇索引(覆盖索引可以模拟多个聚簇索引的情况)。InnoDB的聚簇索引实际上在同一个结构中保存了B-Tree索引和数据行;InnoDB通过主键聚集数据,如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引;InnoDB只聚集在同一个页面中的记录,包含相邻键值的页面可能会相距甚远。
如果正在使用InnoDB表并且没有什么数据需要聚集,那么可以定义一个代理键作为主键,这种主键的数据应该和应用无关,最简单的方法是使用AUTO_INCREMENT自增列。这样可以保证数据行是按顺序写入,对于根据主键做关联操作的性能也会更好。(使用UUID来作为聚簇索引则会很糟糕,它使得聚簇索引的插入变得完全随机,这是最坏的情况,使得数据没有任何聚集特性。)
- 覆盖索引
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。
- 使用索引扫描来排序
MYSQL生成有序结果的两种方式:1.通过排序操作2.按索引顺序扫描(EXPLAIN的type列的值为“index”则说明MYSQL使用了索引扫描来做排序)。只有当索引的列顺序和ORDER BY 子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MYSQL才能够使用索引来对结果做排序。查询关联多张表时,ORDER BY子句饮用的字段全部为第一个表时,才能使用索引做排序。
- 压缩(前缀压缩)索引
对于CPU密集型应用,因为扫描需要随机查找,压缩索引使得MyISAM在索引查找上要慢好几倍。压缩索引的倒序扫描就更慢了。压缩索引需要在CPU内存资源与磁盘之间做权衡。压缩索引可能只需要十分之大小的磁盘空间,如果是I/O密集型应用,对某些查询带来的好处会比成本多很多。
可以再CREATE TABLE 语句中指定PACK_KEYS参数来控制索引压缩的方式。
- 冗余和重复索引
重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引,比如给一个列分别创建了主键、唯一限制和索引,事实上MYSQL的唯一限制和主键限制都是通过索引实现的,因此这样会在相同列上创建三个重复索引
- 未使用索引
在Percona Sever或者MariaDB中先打开userstates服务器变量(默认是关闭的),然后让服务器正常运行一段时间,在通过查询INFORMATION_SCHEMA.INDEX_STATISTICS就能查到每个索引的使用频率。还可以使用Percona Toolkit中的pt-index-usage读取查询日志,并对日志中的每条查询进行EXPLAIN操作,然后打印出关于索引和查询的报告。
- 索引和锁
索引可以让查询锁定更少的行。虽然InnoDB的行锁效率会很高,内存使用也很少,但是锁定行的时候仍然会带来额外开销;其次锁定超过需要的行会增加锁争用并减少并发性。