Table des matières
Préparation de la base de données et de l'index
1 联合索引不满足最左匹配原则
2 使用了select *
3 索引列参与运算
4 索引列参使用了函数
5 错误的Like使用
6 类型隐式转换
7、使用OR操作
8 两列做比较
9 不等于比较
10 is not null
11 not in和not exists
12 order by导致索引失效
13 参数不同导致索引失效
14 Autres
Résumé
Maison base de données tutoriel mysql 15 scénarios d'échec d'index Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

15 scénarios d'échec d'index Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

Mar 01, 2022 am 11:17 AM
mysql 索引失效

Cet article résume et partage 15 scénarios d'échec d'index Mysql afin que tout le monde puisse éviter les pièges. J'espère que cela pourra aider tout le monde !

15 scénarios d'échec d'index Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

Que vous soyez un expert technique ou un novice venant d'entrer dans l'industrie, vous tomberez sur l'écueil d'une base de données Mysql qui n'est pas indexée de temps en temps. Un phénomène courant est qu'un index est ajouté à un champ, mais il ne prend pas effet.

J'ai rencontré un scénario un peu particulier il y a quelques jours. La même instruction SQL a pris effet sous certains paramètres mais pas sous certains paramètres. Pourquoi ?

De plus, qu'il s'agisse d'un entretien ou de la vie quotidienne, vous devez comprendre et apprendre les situations courantes d'échec de l'index Mysql.

Afin de faciliter l'apprentissage et la mémoire, ce document résume 15 situations courantes de non-respect de l'index et les montre avec des exemples pour aider chacun à mieux éviter les pièges. Il est recommandé de le conserver en cas d'urgence.

Préparation de la base de données et de l'index

Créer une structure de table

Afin de vérifier l'utilisation de l'index élément par élément, nous préparons d'abord une table t_user :

CREATE TABLE `t_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `id_no` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '身份编号',
  `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `union_idx` (`id_no`,`username`,`age`),
  KEY `create_time_idx` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
Copier après la connexion

Il y a trois index dans la structure de table ci-dessus :

  • < code>id : est la clé primaire de la base de données ;
  • id:为数据库主键;
  • union_idx:为id_no、username、age构成的联合索引;
  • create_time_idx:是由create_time构成的普通索引;

初始化数据

初始化数据分两部分:基础数据和批量导入数据。

基础数据insert了4条数据,其中第4条数据的创建时间为未来的时间,用于后续特殊场景的验证:

INSERT INTO `t_user` (`id`, `id_no`, `username`, `age`, `create_time`) VALUES (null, &#39;1001&#39;, &#39;Tom1&#39;, 11, &#39;2022-02-27 09:04:23&#39;);
INSERT INTO `t_user` (`id`, `id_no`, `username`, `age`, `create_time`) VALUES (null, &#39;1002&#39;, &#39;Tom2&#39;, 12, &#39;2022-02-26 09:04:23&#39;);
INSERT INTO `t_user` (`id`, `id_no`, `username`, `age`, `create_time`) VALUES (null, &#39;1003&#39;, &#39;Tom3&#39;, 13, &#39;2022-02-25 09:04:23&#39;);
INSERT INTO `t_user` (`id`, `id_no`, `username`, `age`, `create_time`) VALUES (null, &#39;1004&#39;, &#39;Tom4&#39;, 14, &#39;2023-02-25 09:04:23&#39;);
Copier après la connexion

除了基础数据,还有一条存储过程及其调用的SQL,方便批量插入数据,用来验证数据比较多的场景:

-- 删除历史存储过程
DROP PROCEDURE IF EXISTS `insert_t_user`

-- 创建存储过程
delimiter $

CREATE PROCEDURE insert_t_user(IN limit_num int)
BEGIN
  DECLARE i INT DEFAULT 10;
    DECLARE id_no varchar(18) ;
    DECLARE username varchar(32) ;
    DECLARE age TINYINT DEFAULT 1;
    WHILE i < limit_num DO
        SET id_no = CONCAT("NO", i);
        SET username = CONCAT("Tom",i);
        SET age = FLOOR(10 + RAND()*2);
        INSERT INTO `t_user` VALUES (NULL, id_no, username, age, NOW());
        SET i = i + 1;
    END WHILE;

END $
-- 调用存储过程
call insert_t_user(100);
Copier après la connexion

关于存储过程的创建和存储,可暂时不执行,当用到时再执行。

数据库版本及执行计划

查看当前数据库的版本:

select version();
8.0.18
Copier après la connexion

上述为本人测试的数据库版本:8.0.18。当然,以下的所有示例,大家可在其他版本进行执行验证。

查看SQL语句执行计划,一般我们都采用explain关键字,通过执行结果来判断索引使用情况。

执行示例:

explain select * from t_user where id = 1;
Copier après la connexion

执行结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

可以看到上述SQL语句使用了主键索引(PRIMARY),key_len为4;

其中key_len的含义为:表示索引使用的字节数,根据这个值可以判断索引的使用情况,特别是在组合索引的时候,判断该索引有多少部分被使用到非常重要。

做好以上数据及知识的准备,下面就开始讲解具体索引失效的实例了。

1 联合索引不满足最左匹配原则

联合索引遵从最左匹配原则,顾名思义,在联合索引中,最左侧的字段优先匹配。因此,在创建联合索引时,where子句中使用最频繁的字段放在组合索引的最左侧。

而在查询时,要想让查询条件走索引,则需满足:最左边的字段要出现在查询条件中。

实例中,union_idx联合索引组成:

KEY `union_idx` (`id_no`,`username`,`age`)
Copier après la connexion

最左边的字段为id_no,一般情况下,只要保证id_no出现在查询条件中,则会走该联合索引。

示例一

explain select * from t_user where id_no = &#39;1002&#39;;
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

通过explain执行结果可以看出,上述SQL语句走了union_idx这条索引。

这里再普及一下key_len的计算:

  • id_no 类型为varchar(18),字符集为utf8mb4_bin,也就是使用4个字节来表示一个完整的UTF-8。此时,key_len = 18* 4 = 72;
  • 由于该字段类型varchar为变长数据类型,需要再额外添加2个字节。此时,key_len = 72 + 2 = 74;
  • 由于该字段运行为NULL(default NULL),需要再添加1个字节。此时,key_len = 74 + 1 = 75;

上面演示了key_len一种情况的计算过程,后续不再进行逐一推演,知道基本组成和原理即可,更多情况大家可自行查看。

示例二

explain select * from t_user where id_no = &#39;1002&#39; and username = &#39;Tom2&#39;;
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

很显然,依旧走了union_idx索引,根据上面key_len的分析,大胆猜测,在使用索引时,不仅使用了id_no列,还使用了usernameunion_idx : est l'index syndical composé de id_no, nom d'utilisateur, âge ;

create_time_idx : Il s'agit d'un index commun composé de create_time ;

Données d'initialisation

🎜Les données d'initialisation sont divisées en deux parties : les données de base et les données d'importation par lots. . 🎜🎜Les données de base insèrent 4 données, dont l'heure de création de la 4ème donnée est dans le futur, qui est utilisée pour la vérification ultérieure de scénarios particuliers : 🎜
explain select * from t_user where id_no = &#39;1002&#39; and age = 12;
Copier après la connexion
🎜En plus des données de base, il y a aussi une procédure stockée et le SQL qu'elle appelle, ce qui est pratique Insérer des données par lots pour vérifier des scénarios avec beaucoup de données : 🎜
explain select * from t_user where username = &#39;Tom2&#39; and age = 12;
Copier après la connexion
Copier après la connexion
🎜 Concernant la création et le stockage de procédures stockées, vous ne pouvez pas les exécuter temporairement et les exécuter en cas de besoin. 🎜🎜🎜🎜Version de la base de données et plan d'exécution🎜🎜🎜🎜Afficher la version actuelle de la base de données : 🎜
explain select * from t_user where age = 12;
explain select * from t_user where username = &#39;Tom2&#39;;
Copier après la connexion
Copier après la connexion
🎜Ce qui précède est la version de la base de données que j'ai testée : 8.0.18. Bien entendu, tous les exemples suivants peuvent être vérifiés dans d’autres versions. 🎜🎜Affichez le plan d'exécution de l'instruction SQL. Généralement, nous utilisons le mot-clé explain pour juger de l'utilisation de l'index à travers les résultats de l'exécution. 🎜🎜Exemple d'exécution : 🎜
explain select id_no, username, age from t_user where username = &#39;Tom2&#39;;
explain select id_no, username, age from t_user where age = 12;
Copier après la connexion
Copier après la connexion
🎜Résultat d'exécution : 🎜🎜15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)🎜🎜Vous pouvez voir que l'instruction SQL ci-dessus utilise l'index de clé primaire (PRIMARY), et key_len est 4 ; 🎜🎜La signification de key_len ; code> est : indique le nombre d'octets utilisés par l'index. Sur la base de cette valeur, l'utilisation de l'index peut être jugée. Surtout lors de la combinaison d'index, il est très important de juger combien de parties de l'index sont utilisées. 🎜🎜Après avoir préparé les données et les connaissances ci-dessus, commençons par expliquer des exemples spécifiques d'échec d'index. 🎜

1 L'index conjoint ne satisfait pas au principe de correspondance le plus à gauche🎜🎜L'index conjoint suit le principe de correspondance le plus à gauche, 🎜Dans l'index conjoint, le champ le plus à gauche est. correspond en premier🎜. Par conséquent, lors de la création d’un index conjoint, les champs les plus fréquemment utilisés dans la clause Where sont placés à l’extrême gauche de l’index combiné. 🎜🎜Lors d'une requête, si vous souhaitez que les conditions de requête soient indexées, vous devez remplir les conditions suivantes : le champ le plus à gauche doit apparaître dans les conditions de requête. 🎜🎜Dans l'exemple, l'index syndical union_idx se compose de : 🎜
explain select * from t_user where id + 1 = 2 ;
Copier après la connexion
Copier après la connexion
🎜Le champ le plus à gauche est id_no Dans des circonstances normales, tant que id_no apparaît dans les conditions de requête, l'index syndical sera utilisé. 🎜🎜🎜Exemple 1🎜 : 🎜
-- 内存计算,得知要查询的id为1
explain select * from t_user where id = 1 ;
-- 参数侧计算
explain select * from t_user where id = 2 - 1 ;
Copier après la connexion
Copier après la connexion
🎜expliquer le résultat : 🎜🎜15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)🎜🎜Il ressort des résultats de l'exécution de l'explication que l'instruction SQL ci-dessus utilise l'index union_idx. 🎜🎜Ici, nous allons vulgariser le calcul de key_len : 🎜🎜🎜id_no Le type est varchar(18) et le jeu de caractères est utf8mb4_bin, ce qui signifie utiliser 4 octets pour représenter un UTF-8 complet. À l'heure actuelle, key_len = 18* 4 = 72; 🎜Étant donné que le type de champ varchar est un type de données de longueur variable, 2 octets supplémentaires doivent être ajoutés. À l'heure actuelle, key_len = 72 + 2 = 74 ; 🎜Puisque ce champ s'exécute comme NULL (NULL par défaut), 1 octet supplémentaire doit être ajouté. À l'heure actuelle, key_len = 74 + 1 = 75 ; 🎜Ce qui précède démontre le processus de calcul de key_len dans un cas. Nous ne procéderons pas à la déduction une par une à l'avenir. pour connaître la composition et les principes de base. Pour plus de situations, tout le monde peut le consulter vous-même. 🎜🎜🎜Exemple 2🎜 : 🎜
explain select * from t_user where SUBSTR(id_no,1,3) = &#39;100&#39;;
Copier après la connexion
Copier après la connexion
🎜expliquer le résultat : 🎜🎜15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)🎜🎜Évidemment, l'index union_idx est toujours utilisé. Sur la base de l'analyse de key_len ci-dessus, je suppose hardiment que lors de l'utilisation de l'index, non seulement id_no< /code>, utilise également la colonne <code>username. 🎜🎜🎜Exemple 3🎜 : 🎜
explain select * from t_user where id_no like &#39;%00%&#39;;
Copier après la connexion
Copier après la connexion
🎜expliquer le résultat : 🎜

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

走了union_idx索引,但跟示例一一样,只用到了id_no列。

当然,还有三列都在查询条件中的情况,就不再举例了。上面都是走索引的正向例子,也就是满足最左匹配原则的例子,下面来看看,不满足该原则的反向例子。

反向示例

explain select * from t_user where username = &#39;Tom2&#39; and age = 12;
Copier après la connexion
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

此时,可以看到未走任何索引,也就是说索引失效了。

同样的,下面只要没出现最左条件的组合,索引也是失效的:

explain select * from t_user where age = 12;
explain select * from t_user where username = &#39;Tom2&#39;;
Copier après la connexion
Copier après la connexion

那么,第一种索引失效的场景就是:在联合索引的场景下,查询条件不满足最左匹配原则

2 使用了select *

在《阿里巴巴开发手册》的ORM映射章节中有一条【强制】的规范:

【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。 说明:1)增加查询分析器解析成本。2)增减字段容易与 resultMap 配置不一致。3)无用字段增加网络 消耗,尤其是 text 类型的字段。

虽然在规范手册中没有提到索引方面的问题,但禁止使用select * 语句可能会带来的附带好处就是:某些情况下可以走覆盖索引

比如,在上面的联合索引中,如果查询条件是age或username,当使用了select * ,肯定是不会走索引的。

但如果希望根据username查询出id_no、username、age这三个结果(均为索引字段),明确查询结果字段,是可以走覆盖索引的:

explain select id_no, username, age from t_user where username = &#39;Tom2&#39;;
explain select id_no, username, age from t_user where age = 12;
Copier après la connexion
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

无论查询条件是username还是age,都走了索引,根据key_len可以看出使用了索引的所有列。

第二种索引失效场景:在联合索引下,尽量使用明确的查询列来趋向于走覆盖索引

这一条不走索引的情况属于优化项,如果业务场景满足,则进来促使SQL语句走索引。至于阿里巴巴开发手册中的规范,只不过是两者撞到一起了,规范本身并不是为这条索引规则而定的。

3 索引列参与运算

直接来看示例:

explain select * from t_user where id + 1 = 2 ;
Copier après la connexion
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

可以看到,即便id列有索引,由于进行了计算处理,导致无法正常走索引。

针对这种情况,其实不单单是索引的问题,还会增加数据库的计算负担。就以上述SQL语句为例,数据库需要全表扫描出所有的id字段值,然后对其计算,计算之后再与参数值进行比较。如果每次执行都经历上述步骤,性能损耗可想而知。

建议的使用方式是:先在内存中进行计算好预期的值,或者在SQL语句条件的右侧进行参数值的计算。

针对上述示例的优化如下:

-- 内存计算,得知要查询的id为1
explain select * from t_user where id = 1 ;
-- 参数侧计算
explain select * from t_user where id = 2 - 1 ;
Copier après la connexion
Copier après la connexion

第三种索引失效情况:索引列参与了运算,会导致全表扫描,索引失效

4 索引列参使用了函数

示例:

explain select * from t_user where SUBSTR(id_no,1,3) = &#39;100&#39;;
Copier après la connexion
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

上述示例中,索引列使用了函数(SUBSTR,字符串截取),导致索引失效。

此时,索引失效的原因与第三种情况一样,都是因为数据库要先进行全表扫描,获得数据之后再进行截取、计算,导致索引索引失效。同时,还伴随着性能问题。

示例中只列举了SUBSTR函数,像CONCAT等类似的函数,也都会出现类似的情况。解决方案可参考第三种场景,可考虑先通过内存计算或其他方式减少数据库来进行内容的处理。

第四种索引失效情况:索引列参与了函数处理,会导致全表扫描,索引失效

5 错误的Like使用

示例:

explain select * from t_user where id_no like &#39;%00%&#39;;
Copier après la connexion
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

针对like的使用非常频繁,但使用不当往往会导致不走索引。常见的like使用方式有:

  • 方式一:like '%abc';
  • 方式二:like 'abc%';
  • 方式三:like '%abc%';

其中方式一和方式三,由于占位符出现在首部,导致无法走索引。这种情况不做索引的原因很容易理解,索引本身就相当于目录,从左到右逐个排序。而条件的左侧使用了占位符,导致无法按照正常的目录进行匹配,导致索引失效就很正常了。

第五种索引失效情况:模糊查询时(like语句),模糊匹配的占位符位于条件的首部

6 类型隐式转换

示例:

explain select * from t_user where id_no = 1002;
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

id_no字段类型为varchar,但在SQL语句中使用了int类型,导致全表扫描。

出现索引失效的原因是:varchar和int是两个种不同的类型。

解决方案就是将参数1002添加上单引号或双引号。

第六种索引失效情况:参数类型与字段类型不匹配,导致类型发生了隐式转换,索引失效

这种情况还有一个特例,如果字段类型为int类型,而查询条件添加了单引号或双引号,则Mysql会参数转化为int类型,虽然使用了单引号或双引号:

explain select * from t_user where id = &#39;2&#39;;
Copier après la connexion

上述语句是依旧会走索引的。

7、使用OR操作

OR是日常使用最多的操作关键字了,但使用不当,也会导致索引失效。

示例:

explain select * from t_user where id = 2 or username = &#39;Tom2&#39;;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

看到上述执行结果是否是很惊奇啊,明明id字段是有索引的,由于使用or关键字,索引竟然失效了。

其实,换一个角度来想,如果单独使用username字段作为条件很显然是全表扫描,既然已经进行了全表扫描了,前面id的条件再走一次索引反而是浪费了。所以,在使用or关键字时,切记两个条件都要添加索引,否则会导致索引失效。

但如果or两边同时使用“>”和“<”,则索引也会失效:

explain select * from t_user where id  > 1 or id  < 80;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

第七种索引失效情况:查询条件使用or关键字,其中一个字段没有创建索引,则会导致整个查询语句索引失效; or两边为“>”和“<”范围查询时,索引失效

8 两列做比较

如果两个列数据都有索引,但在查询条件中对两列数据进行了对比操作,则会导致索引失效。

这里举个不恰当的示例,比如age小于id这样的两列(真实场景可能是两列同维度的数据比较,这里迁就现有表结构):

explain select * from t_user where id > age;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

这里虽然id有索引,age也可以创建索引,但当两列做比较时,索引还是会失效的。

第八种索引失效情况:两列数据做比较,即便两列都创建了索引,索引也会失效

9 不等于比较

示例:

explain select * from t_user where id_no <> &#39;1002&#39;;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

当查询条件为字符串时,使用”<>“或”!=“作为条件查询,有可能不走索引,但也不全是。

explain select * from t_user where create_time != &#39;2022-02-27 09:56:42&#39;;
Copier après la connexion

上述SQL中,由于“2022-02-27 09:56:42”是存储过程在同一秒生成的,大量数据是这个时间。执行之后会发现,当查询结果集占比比较小时,会走索引,占比比较大时不会走索引。此处与结果集与总体的占比有关。

需要注意的是:上述语句如果是id进行不等操作,则正常走索引。

explain select * from t_user where id != 2;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

第九种索引失效情况:查询条件使用不等进行比较时,需要慎重,普通索引会查询结果集占比较大时索引会失效

10 is not null

示例:

explain select * from t_user where id_no is not null;
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

第十种索引失效情况:查询条件使用is null时正常走索引,使用is not null时,不走索引

11 not in和not exists

在日常中使用比较多的范围查询有in、exists、not in、not exists、between and等。

explain select * from t_user where id in (2,3);

explain select * from t_user where id_no in (&#39;1001&#39;,&#39;1002&#39;);

explain select * from t_user u1 where exists (select 1 from t_user u2 where u2.id  = 2 and u2.id = u1.id);

explain select * from t_user where id_no between &#39;1002&#39; and &#39;1003&#39;;
Copier après la connexion

上述四种语句执行时都会正常走索引,具体的explain结果就不再展示。主要看不走索引的情况:

explain select * from t_user where id_no not in(&#39;1002&#39; , &#39;1003&#39;);
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

当使用not in时,不走索引?把条件列换成主键试试:

explain select * from t_user where id not in (2,3);
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

如果是主键,则正常走索引。

第十一种索引失效情况:查询条件使用not in时,如果是主键则走索引,如果是普通索引,则索引失效

再来看看not exists

explain select * from t_user u1 where not exists (select 1 from t_user u2 where u2.id  = 2 and u2.id = u1.id);
Copier après la connexion

explain结果:

115 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

当查询条件使用not exists时,不走索引。

第十二种索引失效情况:查询条件使用not exists时,索引失效

12 order by导致索引失效

示例:

explain select * from t_user order by id_no ;
Copier après la connexion

explain结果:

15 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

其实这种情况的索引失效很容易理解,毕竟需要对全表数据进行排序处理。

那么,添加删limit关键字是否就走索引了呢?

explain select * from t_user order by id_no limit 10;
Copier après la connexion

explain结果:

215 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

结果依旧不走索引。在网络上看到有说如果order by条件满足最左匹配则会正常走索引, 在当前8.0.18版本中并未出现。所以,在基于order bylimit进行使用时,要特别留意。是否走索引不仅涉及到数据库版本,还要看Mysql优化器是如何处理的。

这里还有一个特例,就是主键使用order by时,可以正常走索引。

explain select * from t_user order by id desc;
Copier après la connexion

explain结果:

215 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

可以看出针对主键,还是order by可以正常走索引。

另外,笔者测试如下SQL语句:

explain select id from t_user order by age;
explain select id , username from t_user order by age;
explain select id_no from t_user order by id_no;
Copier après la connexion

上述三条SQL语句都是走索引的,也就是说覆盖索引的场景也是可以正常走索引的。

现在将idid_no组合起来进行order by

explain select * from t_user order by id,id_no desc;
explain select * from t_user order by id,id_no desc limit 10;
explain select * from t_user order by id_no desc,username desc;
Copier après la connexion

explain结果:

215 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

上述两个SQL语句,都未走索引。

第十三种索引失效情况:当查询条件涉及到order by、limit等条件时,是否走索引情况比较复杂,而且与Mysql版本有关,通常普通索引,如果未使用limit,则不会走索引。order by多个索引字段时,可能不会走索引。其他情况,建议在使用时进行expain验证。

13 参数不同导致索引失效

此时,如果你还未执行最开始创建的存储过程,建议你先执行一下存储过程,然后执行如下SQL:

explain select * from t_user where create_time > &#39;2023-02-24 09:04:23&#39;;
Copier après la connexion

其中,时间是未来的时间,确保能够查到数据。

explain结果:

215 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

可以看到,正常走索引。

随后,我们将查询条件的参数换个日期:

explain select * from t_user where create_time > &#39;2022-02-27 09:04:23&#39;;
Copier après la connexion

explain结果:

215 scénarios déchec dindex Mysql que vous méritez de connaître (pour vous aider à éviter rapidement les pièges)

此时,进行了全表扫描。这也是最开始提到的奇怪的现象。

为什么同样的查询语句,只是查询的参数值不同,却会出现一个走索引,一个不走索引的情况呢?

答案很简单:上述索引失效是因为DBMS发现全表扫描比走索引效率更高,因此就放弃了走索引

也就是说,当Mysql发现通过索引扫描的行记录数超过全表的10%-30%时,优化器可能会放弃走索引,自动变成全表扫描。某些场景下即便强制SQL语句走索引,也同样会失效。

类似的问题,在进行范围查询(比如>、=、

La quatorzième situation d'échec de l'index : Lorsque les conditions de requête sont des requêtes de plage telles que supérieure ou égale à, dans, etc., en fonction de la proportion des résultats de la requête dans l'ensemble des données de la table, l'optimiseur peut abandonner l'index et effectuer une analyse complète de la table.

14 Autres

Bien sûr, il existe d'autres règles pour utiliser ou non un index. Ceci est également lié au fait que le type d'index soit un index B-tree ou un index bitmap, je n'entrerai donc pas dans les détails. .

Les autres choses à dire ici peuvent être résumées comme la quinzième situation d'échec d'index : Autres stratégies d'optimisation de l'optimiseur Mysql Par exemple, l'optimiseur estime que dans certains cas, l'analyse complète de la table est plus rapide que l'indexation, alors l'index. sera rejeté.

Dans ce cas, vous n'avez généralement pas besoin d'y prêter trop d'attention. Lorsque vous découvrez un problème, vous pouvez simplement l'enquêter à un endroit désigné.

Résumé

Cet article résume 15 scénarios d'échec d'index courants pour tout le monde En raison des différentes versions de Mysql, les stratégies d'échec d'index sont également différentes. La plupart des situations d'échec d'index sont claires et un petit nombre d'échecs d'index varie en fonction de la version de Mysql. Par conséquent, il est recommandé de sauvegarder cet article et de le comparer pendant la pratique. Si vous ne parvenez pas à le comprendre avec précision, vous pouvez directement exécuter l'explication pour vérification.

【Recommandation associée : tutoriel vidéo mysql

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

La relation entre l'utilisateur de MySQL et la base de données La relation entre l'utilisateur de MySQL et la base de données Apr 08, 2025 pm 07:15 PM

Dans la base de données MySQL, la relation entre l'utilisateur et la base de données est définie par les autorisations et les tables. L'utilisateur a un nom d'utilisateur et un mot de passe pour accéder à la base de données. Les autorisations sont accordées par la commande Grant, tandis que le tableau est créé par la commande Create Table. Pour établir une relation entre un utilisateur et une base de données, vous devez créer une base de données, créer un utilisateur, puis accorder des autorisations.

MySQL doit-il payer MySQL doit-il payer Apr 08, 2025 pm 05:36 PM

MySQL a une version communautaire gratuite et une version d'entreprise payante. La version communautaire peut être utilisée et modifiée gratuitement, mais le support est limité et convient aux applications avec des exigences de stabilité faibles et des capacités techniques solides. L'Enterprise Edition fournit une prise en charge commerciale complète pour les applications qui nécessitent une base de données stable, fiable et haute performance et disposées à payer pour le soutien. Les facteurs pris en compte lors du choix d'une version comprennent la criticité des applications, la budgétisation et les compétences techniques. Il n'y a pas d'option parfaite, seulement l'option la plus appropriée, et vous devez choisir soigneusement en fonction de la situation spécifique.

Intégration RDS MySQL avec Redshift Zero ETL Intégration RDS MySQL avec Redshift Zero ETL Apr 08, 2025 pm 07:06 PM

Simplification de l'intégration des données: AmazonrDSMysQL et l'intégration Zero ETL de Redshift, l'intégration des données est au cœur d'une organisation basée sur les données. Les processus traditionnels ETL (extrait, converti, charge) sont complexes et prennent du temps, en particulier lors de l'intégration de bases de données (telles que AmazonrDSMysQL) avec des entrepôts de données (tels que Redshift). Cependant, AWS fournit des solutions d'intégration ETL Zero qui ont complètement changé cette situation, fournissant une solution simplifiée et à temps proche pour la migration des données de RDSMySQL à Redshift. Cet article plongera dans l'intégration RDSMYSQL ZERO ETL avec Redshift, expliquant comment il fonctionne et les avantages qu'il apporte aux ingénieurs de données et aux développeurs.

Comment remplir le nom d'utilisateur MySQL et le mot de passe Comment remplir le nom d'utilisateur MySQL et le mot de passe Apr 08, 2025 pm 07:09 PM

Pour remplir le nom d'utilisateur et le mot de passe MySQL: 1. Déterminez le nom d'utilisateur et le mot de passe; 2. Connectez-vous à la base de données; 3. Utilisez le nom d'utilisateur et le mot de passe pour exécuter des requêtes et des commandes.

L'optimisation des requêtes dans MySQL est essentielle pour améliorer les performances de la base de données, en particulier lorsqu'elle traite avec de grands ensembles de données L'optimisation des requêtes dans MySQL est essentielle pour améliorer les performances de la base de données, en particulier lorsqu'elle traite avec de grands ensembles de données Apr 08, 2025 pm 07:12 PM

1. Utilisez l'index correct pour accélérer la récupération des données en réduisant la quantité de données numérisées SELECT * FROMMLOYEESEESHWHERELAST_NAME = 'SMITH'; Si vous recherchez plusieurs fois une colonne d'une table, créez un index pour cette colonne. If you or your app needs data from multiple columns according to the criteria, create a composite index 2. Avoid select * only those required columns, if you select all unwanted columns, this will only consume more server memory and cause the server to slow down at high load or frequency times For example, your table contains columns such as created_at and updated_at and timestamps, and then avoid selecting * because they do not require inefficient query se

MySQL: la facilité de gestion des données pour les débutants MySQL: la facilité de gestion des données pour les débutants Apr 09, 2025 am 12:07 AM

MySQL convient aux débutants car il est simple à installer, puissant et facile à gérer les données. 1. Installation et configuration simples, adaptées à une variété de systèmes d'exploitation. 2. Prise en charge des opérations de base telles que la création de bases de données et de tables, d'insertion, d'interrogation, de mise à jour et de suppression de données. 3. Fournir des fonctions avancées telles que les opérations de jointure et les sous-questionnaires. 4. Les performances peuvent être améliorées par l'indexation, l'optimisation des requêtes et le partitionnement de la table. 5. Prise en charge des mesures de sauvegarde, de récupération et de sécurité pour garantir la sécurité et la cohérence des données.

Comment voir Mysql Comment voir Mysql Apr 08, 2025 pm 07:21 PM

Affichez la base de données MySQL avec la commande suivante: Connectez-vous au serveur: MySQL -U Username -P mot de passe Exécuter les bases de données Afficher les bases de données; Commande pour obtenir toutes les bases de données existantes Sélectionnez la base de données: utilisez le nom de la base de données; Tableau de vue: afficher des tables; Afficher la structure de la table: décrire le nom du tableau; Afficher les données: sélectionnez * dans le nom du tableau;

Comment optimiser les performances MySQL pour les applications de haute charge? Comment optimiser les performances MySQL pour les applications de haute charge? Apr 08, 2025 pm 06:03 PM

Guide d'optimisation des performances de la base de données MySQL dans les applications à forte intensité de ressources, la base de données MySQL joue un rôle crucial et est responsable de la gestion des transactions massives. Cependant, à mesure que l'échelle de l'application se développe, les goulots d'étranglement des performances de la base de données deviennent souvent une contrainte. Cet article explorera une série de stratégies efficaces d'optimisation des performances MySQL pour garantir que votre application reste efficace et réactive dans des charges élevées. Nous combinerons des cas réels pour expliquer les technologies clés approfondies telles que l'indexation, l'optimisation des requêtes, la conception de la base de données et la mise en cache. 1. La conception de l'architecture de la base de données et l'architecture optimisée de la base de données sont la pierre angulaire de l'optimisation des performances MySQL. Voici quelques principes de base: sélectionner le bon type de données et sélectionner le plus petit type de données qui répond aux besoins peut non seulement économiser un espace de stockage, mais également améliorer la vitesse de traitement des données.

See all articles