MySQL索引的一些问题
注意:本文基于MySQL的InnoDB引擎说明。
一、什么是最左前缀原则
对于该表,如果按照name字段来建立索引的话,采用B+树结构,大概的索引如下:
如果要进行模糊查找,查找name 以“张"开头的所有人的ID,即 sql 语句为:
select ID from table where name like '张%'
由于在B+树结构的索引中,叶子节点是一个有序的链表,当我们快速定位到 ID 为 100的张一后,可以直接向右遍历所有张开头的人,直到条件不满足为止。这种定位到最左边,然后向右遍历寻找的方式,就是我们所说的最左前缀原则
。
只是当个索引,在组合索引中更能感受到:
示例:一个(a,b,c)的组合索引。
- 通过a,b条件查询能不能使用或命中这个索引?-----能
- 通过b,c条件查询能不能使用或命中这个索引?-----不能
- 原因:索引文件具有B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
二、为什么用B+树作索引二不用哈希表作索引
1. 不支持模糊查询:哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置,这样的话,如果我们要进行模糊查找的话,显然哈希表这种结构是不支持的,只能遍历这个表。而B+树则可以通过最左前缀原则快速找到对应的数据。
2. 不支持范围查询:如果我们要进行范围查找,例如查找ID为100 ~ 400的人,哈希表同样不支持,只能遍历全表
3. 哈希冲突,影响查询效率:索引字段通过哈希映射成哈希码,如果很多字段都刚好映射到相同值的哈希码的话,那么形成的索引结构将会是一条很长的链表,这样的话,查找的时间就会大大增加
三、主键索引和非主键索引的区别
例如下表(其实就是上面的表中增加了一个k字段),且ID是主键。
主键索引和非主键索引的示意图如下:
其中R代表一整行的值,
由图可以看出,主键索引和非主键索引的区别:主键索引叶子节点存放的是整行数据,非主键索引的叶子节点存放的是主键的值。非主键索引也被称为(二级索引、非聚簇索引),而主键索引也被称为聚簇索引。
1)使用这两种结构进行查询,看看区别:
- 如果查询语句是
select * from table where ID = 100
,即主键查询的方式,则只需要搜索 ID 这棵 B+树。 - 如果查询语句是
select * from table where k = 1
,即非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。
四、聚集索引和非聚集索引的区别
聚集索引和聚簇索引是不同(不知道对不对,我找的资料是这样说的)
1. 聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引
也就是说聚集索引的顺序就是数据的物理存储顺序。它会根据聚集索引键的顺序来存储表中的数据,即对表的数据按索引键的顺序进行排序,然后重新存储到磁盘上。因为数据在物理存放时只能有一种排列方式,所以一个表只能有一个聚集索引。
2. 非聚集索引: 索引顺序与物理存储顺序不同
五、为什么建议使用自增主键作索引
如果主键是自增的,每次插入的 ID 都会比前面的大,那么每次只需要在后面插入就行, 不需要移动位置、分裂等操作。从性能和存储空间方面考量,自增主键往往是更合理的选择。
六、覆盖索引
select * from T where k between 3 and 5 这种查询K的索引搜索到主键 然后搜索主键的索引 拿到具体的信息有回表
select ID from T where k between 3 and 5 这时只需要查 ID 的值,而 ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表 由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
也就是说,你要找的数据已经在索引上,不需要再回表。
七、一个关于索引的题
CREATE TABLE `geek` (`a` int(11) NOT NULL,`b` int(11) NOT NULL,`c` int(11) NOT NULL,`d` int(11) NOT NULL,PRIMARY KEY (`a`,`b`),KEY `c` (`c`),KEY `ca` (`c`,`a`),KEY `cb` (`c`,`b`) ) ENGINE=InnoDB;
问题:哪个索引可以去掉?
主键 a,b 的聚簇索引组织顺序相当于 order by a,b ,也就是先按 a 排序,再按 b 排序,c 无序。
索引 ca 的组织是先按 c 排序,再按 a 排序,同时记录主键
所以索引ca 与 索引c 的数据是一模一样的
索引 cb 的组织是先按 c 排序,在按 b 排序,同时记录主键,
所以结论是ca可以去掉,cb保留。