相信没有人会故意创建重复冗余的索引。许多重复和冗余的索引是无意中创建的。今天宋哥就给大家分享一下。问题。因为我们在日常使用MySQL的时候基本都会用到InnoDB引擎,所以下面的讨论主要是基于InnoDB引擎的B+Tree索引,其他的哈希索引和全文索引不在讨论范围之内。1.与联合索引重复上一篇宋哥通过几篇文章给大家分享了联合索引,包括它涉及到的覆盖索引,前缀匹配等。联合索引好用,但是对联合索引的理解不到位。如果是这样,可能会创建以下重复索引:CREATETABLE`user2`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`username`varchar(32)COLLATEutf8mb4_unicode_ciDEFAULTNULL,`address`varchar(32)COLLATEutf8mb4_unicode_ciDEFAULTNULL,`password`varchar(32)COLLATEutf8mb4_unicode_ciDEFAULTNULL,`email`varchar(16)COLLATEutf8mb4_unicode_ciDEFAULTNULL,PRIMARYKEY(`id`),KEY`user_index1`(`username`,`address`),KEY`user_index2`(`username`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_unicode_ci;可以看到,这里创建了两个索引:user_index1:这个索引包含两个字段,username在前面,address在后面。user_index2:该索引包含一个字段用户名。其实MySQL中的like关键字也是可以使用索引的!宋大哥在文章中谈到了索引的最左匹配原则,即(用户名,地址)索引可以作为联合索引,也可以通过最左匹配作为单独的(用户名)索引原则。因此,没有必要为用户名字段创建单独的索引,这样会减慢增删改查的速度。但是怎么说呢,上面的结论适用于99%的场景,可能会有一些特殊情况,比如你想在(username)和一个特别长的字段之间建立一个联合索引,如果你使用username字段单独去搜索,效率可能会降低。这时候根据搜索的重要程度,需要建立重复索引。2.将主键添加到联合索引,看看下面的索引:CREATETABLE`user2`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`username`varchar(32)COLLATEutf8mb4_unicode_ciDEFAULTNULL,`address`varchar(32)整理utf8mb4_unicode_ciDEFAULTNULL,`password`varchar(32)整理utf8mb4_unicode_ciDEFAULTNULL,`email`varchar(16)整理utf8mb4_unicode_ciDEFAULTNULL,PRIMARYKEY(`id`),KEY`user_index`id(`username`,))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_unicode_ci;名为user_index的索引包含两个字段username和id,其中id是主键。什么是MySQL中的“后表”?文中宋哥和大家聊了聊,索引按照物理存储方式可以分为聚簇索引和非聚簇索引。我们所说的主键索引其实就是聚集索引(ClusteredIndex);除了主键索引,其他的都称为非主键索引,非主键索引也称为二级索引(SecondaryIndex),或称为辅助索引。对于主键索引和非主键索引,使用的数据结构是B+Tree。唯一不同的是叶子节点存储的内容不同:主键索引的叶子节点存储的是完整的一行数据。非主键索引的叶子节点存储主键值和索引列的值。这是两者最大的区别。既然叶节点中已经存在主键,那么当然不把主键加入到联合索引中。好了,几个小注意点,希望对朋友们有所启发。参考资料:《高性能 MySQL》
