1、聚簇索引(索引组织表)
聚簇索引不是一个索引类型,而是一种储存方式。在InnoDB中,聚簇索引在同一个结构中保存了B-Tree索引和数据行,数据行储存在索引的叶子页;因为无法同时把数据行存放在两个不同的地方,所以一个表只能存在一个聚簇索引;索引是有储存引擎实现的;
InnoDB通过主键聚集数据,”被索引的列“就是主键列,如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,那InnoDB会隐式的定义一个主键作为聚簇索引
优点
- 相关数据聚集在一起,查询的时候,可以减少IO次数
- 数据访问更快,因为数据行跟索引同放一个B-Tree中
- 使用覆盖索引的时候可以直接使用页节点中的主键值,因为二级索引保存的是主键的值
缺点
- 聚簇索引主要针对磁盘IO,特别是机械硬盘,如果数据索引是直接放在内存,那就没什么优势了
- 插入速度严重依赖于插入顺序
- 更新聚簇索引列的代价很高,因为要移动位置,就会存在”页分裂“,行变得稀疏,数据储存不连续,表占用空间变大,进而导致全表扫描变慢
- 二级索引变得更大,因为二级索引的叶子节点包含了主键列的值,数据行访问需要回表
最佳实践
- 如果没有实际意义的主键来聚集数据,那就定义一个自增主键(AUTO_INCREMENT),可以保证数据行是按顺序写入,根据主键做关联操作的性能也会更好
- 最好避免随机的(不连续且值的分布范围非常大,如UUID)聚簇索引,特别是对IO密集型的应用;用UUID来做聚簇索引会使得聚簇索引插入变得完全随机,这是最坏的情况!
- 尽可能按主键顺序插入数据!
- 尽可能使用单调增加的聚簇建的值来插入新行
顺序主键有可能产生的问题:在高并发的工作负载,有可能会成为一个性能瓶颈,并发插入可能导致间隙锁竞争;另一个是AUTO_INCREMENT锁机制,可以通过配置innodb_autoinc_lock_mode配置;
2、覆盖索引
如果一个索引包含所有需要查询的字段的值,那就称之为“覆盖索引”;只能使用B-Tree索引做覆盖索引;
优点
- 减少数据访问量,因为不需要回表
- 范围查询会快得多,因为索引的值有顺序
数据从储存引擎拉到服务器层,再根据查询条件过滤
3、索引可以用来排序
MySQL可以使用同一个索引既满足排序,又可以用于查找行;
只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向都一样时,MySQL才能够使用索引来对结果做排序;
如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引做排序;
条件:满足索引的最左前缀原则(前导列为常量除外)
4、不要创建冗余、重复的索引
比如 (A, B),(A),第一个包括了第二个,是冗余索引
还有一些索引名称不同,但是属于同一列的,是重复索引,都应该避免
应该删除永远都不使用的索引
5、索引可以减少锁定的行
索引可以让查询锁定更少的行,提高并发性能
如果索引无法过滤无效的行,那么在InnoDB检索到数据并返回给服务器层以后,MySQL服务器才能应用WHERE子句。这时已经无法避免锁定行了,InnoDB已经锁定了这些行,到适当的时候才会释放。(MySQL5.1以后就可以在服务器端过滤掉行后就立刻释放锁了)
案例诀窍
可以通过SEX IN ('m', 'f')这样来强制使用索引
范围查询最好放在最后,尽可能使用更多的索引列
一些范围查询,可以改成多个等值查询
一些耗时长、无法优化的查询:反范式化、预先计算和缓存是解决这类查询的仅有策略,一个更好的办法是限制用户能够翻页的数量
网友评论