Maison > Questions et réponses > le corps du texte
J'ai vu l'information sur Internet et j'ai dit :
in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
阿神2017-05-18 10:58:50
Les valeurs continues sont bien sûr comprises entre, ce qui réduit l'analyse, et si la plage de in dépasse un certain nombre, la table entière sera supprimée par défaut 9 ou plus ou moins est oublié
.Réponse supplémentaire aux commentaires ci-dessous :
Dans la liste complète, cela dépend de la situation. La réponse ci-dessus n'est qu'un résumé approximatif de mémoire. L'ami d'en bas est plus sérieux, je vais l'expliquer ici à nouveau. un nombre. C'est un ratio, environ 25%-35%. Si vous voulez demander combien c'est, je suis désolé car mon niveau est limité et je ne peux pas le confirmer sans lire le code source. Et le ratio d'environ 30 ne signifie pas qu'une analyse complète de la table doit être effectuée, car mysql dispose également d'une analyse d'index, ce qui signifie que si le contenu sélectionné peut être trouvé dans votre index, bien sûr, il n'analysera pas la table entière, comme ce qui suit Dans les exemples, sélectionnez id from ttt Where id in (..); et sélectionnez * from ttt Where id in (...) ; le précédent est définitivement une analyse de clé primaire, même si vous entrez tous les id, il s'agira toujours d'une analyse de clé primaire, et la situation suivante est la situation de ce pourcentage. Veuillez vous référer à l'exemple ci-dessous pour plus de détails ^_^
. Entre.Pourquoi est-ce bon ?En plus de réduire l'analyse pour un accès continu au segment d'index, il existe également une situation où lors de la récupération des données via l'adressage du disque, une partie des données proches de la première valeur sera lue par défaut (il y en a). un algorithme de probabilité tel que lorsqu'une donnée est récupérée, les données à proximité sont également très volumineuses.) Il existe donc une situation où les données redondantes sont supprimées en même temps pour éviter plusieurs adressages. utiliser la valeur continue entre entre est approprié
mysql> select * from ttt;
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | I17021234001 |
| 2 | IC17031234002 |
| 3 | C17041234003 |
| 4 | IAsEw1234001 |
| 5 | I17021234001A2 |
| 6 | IC17031234002A2 |
| 7 | C17041234003A2 |
| 8 | IAsEw1234001A2 |
| 9 | I17021234001A2 |
| 10 | IC17031234002A2 |
| 11 | C17041234003A2 |
| 12 | IAsEw1234001A2 |
| 13 | I17021234001A2A2 |
| 14 | IC17031234002A2A2 |
| 15 | C17041234003A2A2 |
| 16 | IAsEw1234001A2A2 |
| 17 | I17021234001A2 |
| 18 | IC17031234002A2 |
| 19 | C17041234003A2 |
| 20 | IAsEw1234001A2 |
+----+-------------------+
20 rows in set (0.00 sec)
mysql> show create table ttt;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ttt | CREATE TABLE `ttt` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> explain select * from ttt where id in (1,2,3,4,5,6);
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | ttt | ALL | PRIMARY | NULL | NULL | NULL | 20 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from ttt where id in (1,2,3,4,5);
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | ttt | range | PRIMARY | PRIMARY | 4 | NULL | 5 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from ttt where id in (1,2,3);
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | ttt | range | PRIMARY | PRIMARY | 4 | NULL | 3 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from ttt where id in (1,2,3,4,5,6,7);
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | ttt | ALL | PRIMARY | NULL | NULL | NULL | 20 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select id from ttt where id in (1,2,3,4,5,6,7);
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | ttt | index | PRIMARY | PRIMARY | 4 | NULL | 20 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select name from ttt where id in (1,2,3,4,5,6,7);
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | ttt | ALL | PRIMARY | NULL | NULL | NULL | 20 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
阿神2017-05-18 10:58:50
Selon la structure de stockage de l'index B-tree dans la base de données, l'adresse physique pointant vers les données est stockée dans le nœud feuille, et cette adresse physique est ordonnée lorsqu'il existe un index clusterisé.
如果是连续数值,between在找到第一个匹配值后,则直接从该地址往后搜索,直到最后一个元素为止。这样就不会对后续值进行索引扫描,因此速度快了。
对于in操作,不大清楚,但是估计应该会对全索引进行扫描吧。
淡淡烟草味2017-05-18 10:58:50
Lorsque vous utilisez between, il vous suffit de faire correspondre les limites supérieure et inférieure, ce sera donc plus rapide ; chaque entrée doit être relue, ce qui entraînera une analyse complète du tableau.