1、 复合索引的建立以及最左前缀原则
假设你在表的state、city和zip数据列上建立了复合索引。索引中的数据行按照state/city/zip次序排列,因此它们也会自动地按照state/city和state次序排列。这意味着,即使你在查询中只指定了state值,或者指定state和city值,MySQL也可以使用这个索引。因此,这个索引可以被用于搜索如下所示的数据列组合:state, city, zipstate, citystateMySQL不能利用这个索引来搜索~没有包含在最左前缀的内容~。例如,如果你按照city或zip来搜索,就不会使用到这个索引。如果你搜索给定的state和具体的ZIP代码(索引的1和3列),该索引也是不能用于这种组合值的,尽管MySQL可以利用索引来查找匹配的state从而缩小搜索的范围。如果你考虑给已经索引过的表添加索引,那么就要考虑你将增加的索引是否是已有的多列索引的最左前缀。如果是这样的,不用增加索引,因为已经有了(例如,如果你在state、city和zip上建立了索引,那么没有必要再增加state的索引)。复制代码
2、order by
的字段必须放在索引的最后面
假设表persons
有如下信息段
CREATE TABLE `persons` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `uuid` varchar(60) NOT NULL COMMENT 'uuid', `unitcode` varchar(30) NOT NULL COMMENT '单位编码', `code1` varchar(36) DEFAULT NULL COMMENT '员工号/编码', `name1` varchar(50) DEFAULT NULL COMMENT '姓名', /* * ... */ `s_date` date DEFAULT NULL COMMENT '员工档案建档日期', `logout` smallint(6) DEFAULT NULL COMMENT '在职状态', /* * ... */ `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `persons_uuid_unique` (`uuid`), KEY `persons_name1_unitcode_index` (`name1`,`unitcode`), /* * ... */ KEY `persons_name1_unitcode_logout_deleted_at_index` (`name1`, `unitcode`,`logout`,`deleted_at`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=34199 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;复制代码
有如下查询语句
-- sql1desc select * from `persons` where `unitcode` like '000%' and `logout` = '0' and `persons`.`deleted_at` is null order by `name1` limit 15 offset 0-- sql2desc select `unitcode`, `name1` from `persons` where `unitcode` like '000%' and `logout` = '0' and `persons`.`deleted_at` is null order by `name1` limit 15 offset 0复制代码
- 上面的
sql1
中不会用到索引,sql2
中才用到索引 - 要使
sql1
中用到索引必须将sql查询语句
中where
中没有出现,只是在order by
中出现的列名
放到索引
的最后面,将 索引persons_name1_unitcode_logout_deleted_at_index
改为以下即可。
/* * ... */KEY `persons_name1_unitcode_logout_deleted_at_index` (`unitcode`,`logout`,`deleted_at`, `name1`) USING BTREE复制代码