TIMESTAMP 字段上的 MYSQL 索引不使用索引进行范围查询

标签 mysql indexing

我在 mysql 表中有以下行

+--------------------------------+----------------------+------+-----+---------+----------------+
| Field                          | Type                 | Null | Key | Default | Extra          |
+--------------------------------+----------------------+------+-----+---------+----------------+
| created_at                     | timestamp            | YES  | MUL | NULL    |                |

字段上存在以下索引

*************************** 6. row ***************************
        Table: My_Table
   Non_unique: 1
     Key_name: IDX_My_Table_CREATED_AT
 Seq_in_index: 1
  Column_name: created_at
    Collation: A
  Cardinality: 273809
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment:

我正在尝试优化以下查询以将 IDX_My_Table_CREATED_AT 索引用于范围条件

SELECT * FROM My_Table as main_table  WHERE ((main_table.created_at >= '2013-07-01 05:00:00') AND (main_table.created_at <= '2013-11-09 05:59:59'))\G

当我在选择查询上使用 EXPLAIN 时,我得到以下信息:

+----+-------------+------------+------+---------------------------------+------+---------+------+--------+-------------+
| id | select_type | table      | type | possible_keys                   | key  | key_len | ref  | rows   | Extra       |
+----+-------------+------------+------+---------------------------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | main_table | ALL  | IDX_My_Table_CREATED_AT         | NULL | NULL    | NULL | 273809 | Using where |
+----+-------------+------------+------+---------------------------------+------+---------+------+--------+-------------+

问题是 IDX_My_Table_CREATED_AT 索引未用于此范围条件,即使它是 BTREE 索引,因此应该适用于查询。

奇怪的是,如果我尝试对该列进行单值查找,则会使用索引。

EXPLAIN SELECT * FROM My_Table as main_table  WHERE (main_table.created_at = '2013-07-01 05:00:00');
+----+-------------+------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+
| id | select_type | table      | type | possible_keys                 | key                           | key_len | ref   | rows | Extra       |
+----+-------------+------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | main_table | ref  | IDX_My_Table_CREATED_AT index | IDX_My_Table_CREATED_AT index | 5       | const |    1 | Using where |
+----+-------------+------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+

为什么索引没有被用于范围条件?我曾尝试将查询更改为使用 BETWEEN,但这并没有改变任何东西。

最佳答案

答案很简单..

MySQL 优化器是基于成本的,优化器计算出全表扫描是获取记录的最佳方式(最便宜)。

因为所需的范围看起来像是查看行 (EXPLAIN) 和基数的完整表格。这些数字是相等的。

如果 MySQL 优化器确实使用索引,则相对成本会高得多,因为随机读取(慢)需要查找记录

故事的座右铭在这种情况下,全表扫描并不是世界末日......只是接受它......

关于TIMESTAMP 字段上的 MYSQL 索引不使用索引进行范围查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20764807/

相关文章:

php - 如何将这部分代码转换为 PHP 中的准备语句?

php - 如何将表单字段值发送到 WordPress 中的 php mysql 查询?

mysql - 使用 group by 进行慢速查询

python - Numpy 矩阵索引等价

php - 如何使用php一次从mysql数据库中获取一个单词

php - 如何将不带换行符的字符串连接到 MySQL 中?

sql-server - 索引如何成为表插入/更新/删除的开销?

C++从迭代器中获取整数索引值

c++ - MongoDb 使用 C++ 驱动程序创建稀疏索引

MySql 查询 : Total Average for multiple tables