Maison > Questions et réponses > le corps du texte
J'ai un modèle appelé CacheSync et mysql montre qu'il a un index :
mysql> show indexes from cache_syncs; +-------------+------------+---------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------------+------------+---------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | cache_syncs | 0 | PRIMARY | 1 | id | A | 90878 | NULL | NULL | | BTREE | | | | cache_syncs | 1 | index_cache_syncs_on_created_at | 1 | created_at | A | 18175 | NULL | NULL | YES | BTREE | | | +-------------+------------+---------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 2 rows in set (0.01 sec)
Mais quand je suis allé l'expliquer, il m'a dit qu'il n'utilisait pas d'index :
CacheSync.where("created_at < ?", (Time.now - 1.hour).to_time).explain => EXPLAIN for: SELECT `cache_syncs`.* FROM `cache_syncs` WHERE (created_at < '2022-06-13 19:37:23.316439') +----+-------------+-------------+------+---------------------------------+------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------------+------+---------------------------------+------+---------+------+-------+-------------+ | 1 | SIMPLE | cache_syncs | ALL | index_cache_syncs_on_created_at | NULL | NULL | NULL | 93651 | Using where | +----+-------------+-------------+------+---------------------------------+------+---------+------+-------+-------------+ 1 row in set (0.00 sec)
Pourquoi ne pas utiliser l'index ?
Merci pour votre aide, Kévin
P粉4211197782024-03-22 10:04:01
D'après mon expérience, si l'optimiseur estime que votre condition correspond à plus de 20 % du tableau, il reviendra à une analyse du tableau. Il suppose que lire toutes les lignes de l'index clusterisé est plus rapide que de rechercher les valeurs dans l'index secondaire, puis d'effectuer une autre recherche pour obtenir les lignes correspondantes de la table.
Le seuil de 20 % n’est pas une caractéristique officielle, c’est juste ce que j’ai observé. Il n'est pas configurable dans les versions actuelles de MySQL.
Vous pouvez utiliser des indices d'index pour le convaincre que l'analyse de table est trop coûteuse :
SELECT ... FROM mytable FORCE INDEX (index_cache_syncs_on_created_at) WHERE ...
Il effectuera une analyse de table uniquement si l'index que vous spécifiez n'est pas lié aux conditions de la requête.
Voir https://dev.mysql.com/doc/refman/8.0/en/index-hints.html pour plus d'informations sur les astuces d'index.
Je ne suis pas un développeur Rails, mais cette ancienne réponse montre un moyen de transmettre la syntaxe des indices d'index à Rails : https://stackoverflow.com/a/13904227/20860 Je ne sais pas si c'est toujours la version actuelle pratique.