索引的作用是“排列好次序,使得查询时可以快速找到”.
唯一索引
唯一索引是在表上一个或者多个字段组合建立的索引,这个或者这些字段的值组合起来在表中不可以重复。如学生表中的“学号”
非唯一索引
非唯一索引是在表上一个或者多个字段组合建立的索引,这个或者这些字段的值组合起来在表中可以重复,不要求唯一。如学生表中的‘成绩’。
主键索引
主键索引(主索引)是唯一索引的特定类型。表中创建主键时自动创建的索引 。一个表只能建立一个主索引。
聚集索引(聚簇索引)
聚集索引(聚簇索引),表中记录的物理顺序与键值的索引顺序相同。一个表只能有一个聚集索引。
聚集索引和非聚集索引的区别?分别在什举情冴下使用?
聚集索引与非聚集索引的根本区删是表中记录的物理顺序与索引的排列顺序是否一致。
聚集索引的表中记录的物理顺序与索引的排列顺序一致。
优点是查询速度快,因为一旦具有第一个索引值的记录被找到,具有连续索引值的记录也一定物理的紧跟其后。
缺点是对表进行修改速度较慢,这是为了保持表中的记录的物理顺序与索引的顺序一致,而把记录插入到数据页的相应位置,必项在数据页中进行数据重排,降低了执行速度。在插入新记录时数据文件为了维持 B+Tree 的特性而频繁的分裂调整,十分低效。
建议使用聚集索引的场合为:
某列包含了小数目的不同值。
排序和范围查找。
非聚集索引的记录的物理顺序和索引的顺序不一致。
其他方面的区别:
1.聚集索引与非聚集索引都采用了 B+树的结构,但非聚集索引的叶子层并不与实际的数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针的方式。聚集索引的叶子节点就是数据节点,而非聚集索引的叶子节点仍然是索引节点。
2.非聚集索引添加记录时,不会引起数据顺序的重组。看上去聚簇索引的效率明显要低于非聚簇索引, 因为每次使用辅助索引检索都要经过两次 B+树查找, 这不是多此一举吗? 聚簇索引的优势在哪?
由于行数据的叶子节点存储在一起, 这样主键和行数据是一起被载入内存的, 找到叶子节点就可以立刻将行数据返回了, 如果按照主键 Id 来组织数据, 获得数据更快。
辅助索引使用主键作为"指针", 而不是使用地址值作为指针的好处是, 减少了当出现行移动或者数据页分裂时, 辅助索引的维护工作, InnoDB 在移动行时无需更新辅助索引中的这个"指针"。 也就是说行的位置会随着数 据
库里数据的修改而发生变化, 使用聚簇索引就可以保证不管返个主键 B+树的节点如何发化, 辅助索引树都不会受到影响。
建议使用非聚集索引的场合为:
此列包含了大数目的丌同值;
频繁更新的列
索引实现机制
虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。
第一个重大区别是InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是分离开的,索引文件只保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶
节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
第二个与MyISAM索引的丌同是InnoDB的辅劣索引data域存储相应记录的主键的值而不是地址。换句话说,InnoDB 的所有辅劣索引都引用主键作为data域。
聚集索引这种实现方式使得按主键的搜索十分高效,但是辅劣索引搜索
需要检索两遍索引:首先检索辅劣索引获得主键,然后用主键的主索引中检索获得记录。
了解不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅劣索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。
索引建立原则
-
.最左前缀匹配原则,mysql 会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,范围查询会导致组合索引半生效。比如 a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,c 可
以用到索引,d 是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d 的顺序可以任意调整。where范围查询要放在最后 (这不绝对,但可以利用一部分索引)。 -
特别注意:and 之间的部分可以乱序,比如 a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮助优化成索引可以识别的形式。where 字句有 or 出现还是会遍历全表。
-
尽量选择区分度高的字段作为索引,某字段的区分度的公式是 count(distinctcol)/count(*),表示字段不重复的比例,比例越大,我们扫描的记录数越少,查找匹配的时候可以过滤更多的行, 唯一索引的区分度是 1,而一些状态、性别字段可能在大数据面前区分度就是 0。
-
不在索引列做运算或者使用函数。
-
尽量扩展索引,不要新建索引。比如表中已经有 a 的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
-
Where 子句中经常使用的字段应该创建索引,分组字段或者排序字段应该创建索引,两个表的连接字段应该创建索引。
-
like 模糊查询中,右模糊查询(321%)会使用索引,而%321 和%321%会放弃索引而使用全局扫描。