mysql 索引 - 建议

/**

针对mysql 5.6.41 测试

建表

DROP TABLE IF EXISTS user_index;
CREATE TABLE user_index (
id int(11) NOT NULL AUTO_INCREMENT,
userId int(11) NOT NULL,
age int(11) NOT NULL,
name varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY idx_userId (userId),
KEY idx_name (name) USING BTREE,
KEY idx_userid_age (userId,age) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- Table structure for user_job


DROP TABLE IF EXISTS user_job;
CREATE TABLE user_job (
id int(11) NOT NULL,
userId int(11) NOT NULL,
job varchar(255) DEFAULT NULL,
name varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
KEY idx_name (name) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


-- Table structure for user_job_utf8mb4


DROP TABLE IF EXISTS user_job_utf8mb4;
CREATE TABLE user_job_utf8mb4 (
id int(11) NOT NULL,
userId int(11) NOT NULL,
job varchar(255) DEFAULT NULL,
name varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
KEY idx_name (name(191)) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

SET FOREIGN_KEY_CHECKS = 1;

explain 主要字段

url: https://blog.csdn.net/qq_36120342/article/details/85333749

possible_keys: 表示查询时可能使用的索引。如果是空的,没有相关的索引。这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引

key: 显示MySQL实际决定使用的索引。如果没有索引被选择,是NULL

key_len: 使用到索引字段的长度

注:key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

mysql有优化器 所以一切索引有效性均已实际开发环境为主。

摘之: https://github.com/whx123/JavaHome/blob/master/Mysql基础学习/后端程序员必备:索引失效的十大杂症.md

######## 1.查询条件包含or,可能导致索引失效
explain select * from user_index where userid = 1 or age = 1;

age没有索引这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程: 全表扫描 + 索引扫描 + 合并,不如一开始就走全表扫描,直接一遍扫描就完事。

mysql是有优化器的,处于效率与成本,遇到or条件,索引可能失效.

######## 2.如字段类型是字符串,where时一定用引号括起来,否则索引失效
explain select * from user_index where name = 1 ; (错)
explain select * from user_index where name = '1' ;(对)

隐式类型转换

######## 3.like 与 not like通配符可能导致索引失效。
explain select * from user_index where name like '%1' ; (错)

explain select * from user_index where name like '1%' ; (对)# 把%放后面
explain select * from user_index where name not like '1%' ; (错)# 把%放后面

explain select name from user_index where name like '%1' ; (对) # 把%加回来,改为只查索引的字段,发现还是走索引,好惊喜,好意外。(覆盖索引)
explain select name from user_index where name not like '%1' ; (对)

使用explain,可以通过输出的extra列来判断,对于一个索引覆盖查询,显示为using index,MySQL查询优化器在执行查询前会决定是否有索引覆盖查询

覆盖索引是在SQLServer2005中引入的概念,只能建立在非聚集索引的基础上,通常情况下,非聚集索引的索引页是不包含真实数据的,只存储着指向数据页中数据行的指针,而覆盖索引则是通过将数据存储在索引页上,从而在查找对应数据的时候,只要找到索引页就可以访问到数据,无需再去查询数据页,所以说这个索引是数据“覆盖”的。

https://www.cnblogs.com/teroy/p/4159009.html(sqlserver)

https://www.cnblogs.com/chenpingzhao/p/4776981.html (mysql)

######## 4.联合索引,查询时的条件列不是联合索引(idx_userid_age,userId在前,age在后)中的第一个列,索引失效。
explain select * from user_index where age = 1 and userid = 1; (错) # 这是我们要的索引(idx_userid_age),哈
explain select * from user_index where userid = 1 and age = 1; (对)

最左匹配原则

当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。

######## 5.在索引列上使用mysql的内置函数,索引失效。
explain select * from user_index where SUBSTR(name,0,1); (错)

######## 6.对索引列运算(如,+、-、*、/),索引失效。
explain select * from user_index where userId+1 = 2; (错)

######## 7.索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效
explain select * from user_index where userId <> 2; (错)
explain select * from user_index where userId != 2; (错)
explain select * from user_index where userId not in (1,2); (错)

######## 8.索引字段上使用is null, is not null,可能导致索引失效。
explain select * from user_index where userId is not null; (错)
explain select * from user_index where userId is null; (错)

null 很特殊,除了 text 这种长字段,请在系统初始化,或者历史数据处理过程中置为 '' 或者 0

######## 9.左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
explain select * from user_index a inner join user_job b on a.name = b. name; (对)
explain select * from user_index a inner join user_job_utf8mb4 b on a.name = b. name; (对)

######## 10.mysql估计使用全表扫描要比使用索引快,则不使用索引

当表的索引被查询,会使用最好的索引,除非优化器使用全表扫描更有效。优化器优化成全表扫描取决与使用最好索引查出来的数据是否超过表的30%的数据。

不要给'性别'等增加索引。如果某个数据列里包含了均是"0/1"或“Y/N”等值,即包含着许多重复的值,就算为它建立了索引,索引效果不会太好,还可能导致全表扫描。

总结 : 结合执行计划 explain 和 具体场景分析,不要按部就班,墨守成规

  • */
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容