Ich habe ein Modell namens CacheSync und MySQL zeigt an, dass es einen Index hat:
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)
Aber als ich es erklären wollte, hieß es, dass kein Index verwendet würde:
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)
Warum nicht den Index verwenden?
Vielen Dank für Ihre Hilfe, Kevin
根据我的经验,如果优化器估计您的条件与表的 20% 以上匹配,它将回退到表扫描。它猜测从聚集索引中读取所有行比在二级索引中查找值更快,然后再进行一次查找以从表中获取相应的行。
20% 的阈值不是任何官方功能,这只是我观察到的。它在当前版本的 MySQL 中不可配置。
您可以使用索引提示来说服它表扫描的成本过高:
只有当您指定的索引与查询中的条件无关时,它才会执行表扫描。
参见https://dev.mysql.com/ doc/refman/8.0/en/index-hints.html 有关索引提示的更多信息。
我不是 Rails 开发人员,但这个旧答案显示了一种向 Rails 传递索引提示语法的方法:https:// stackoverflow.com/a/13904227/20860 我不知道这是否仍然是目前的做法。