Mysql 在where子句中使用datetime索引

Mysql 在where子句中使用datetime索引,mysql,sql,date,query-optimization,where-clause,Mysql,Sql,Date,Query Optimization,Where Clause,我有一个有2亿行的表,其中索引是在“created_at”列中创建的,该列是datetime数据类型 显示创建表[tablename]输出: create table `table` (`created_at` datetime NOT NULL) PRIMARY KEY (`id`) KEY `created_at_index` (`created_at`) ENGINE=InnoDB AUTO_INCREMENT=208512112 DEFAULT CHARSET=utf8mb4

我有一个有2亿行的表,其中索引是在“created_at”列中创建的,该列是datetime数据类型

显示创建表[tablename]输出:

 create table `table`
 (`created_at` datetime NOT NULL)
 PRIMARY KEY (`id`)
 KEY `created_at_index` (`created_at`)
 ENGINE=InnoDB AUTO_INCREMENT=208512112 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'
在2020年4月1日至2020年5月28日期间创建的_

我只想获取超过2020-05-15 23:00:00的行

当我跑步时:

EXPLAIN SELECT created_at
          FROM table
         where created_at >= '2020-05-15 23:00:00';
它说它输出:

rows       Extra
200mil   Using Where
key_len    ref     rows     Extra
  5        const    51      Using index condition
我的理解是,在RDMS中,如果没有索引行没有排序,但当您在列上创建索引时,它是按排序的,因此在找到“2020-05-15 23:00:00”之后,它将简单地返回之后的所有行

另外,由于它的基数是7mil,我认为使用索引比使用全表扫描要好

是不是因为我输入了一个字符串?但是当我尝试的时候

 where created_at >= date('2020-05-15 23:00:00');
还是一样

输出语法错误

mysql刚刚决定进行全表扫描更有效吗

编辑:

使用相等的

EXPLAIN SELECT created_at
          FROM table
         where created_at = '2020-05-15';
产出:

key_len    ref     rows     Extra
  5        const    51 
在where子句中,如果我将字符串更改为日期('2020-05-15'),它将输出:

rows       Extra
200mil   Using Where
key_len    ref     rows     Extra
  5        const    51      Using index condition

这是否意味着第一个相等的查询没有使用索引?

您的所有查询都将利用在创建的
列上的索引。MySQL总是在与
where
子句的谓词匹配时使用索引

explain
s的输出确实表明您没有此索引,这一点由
create table
的输出确认

只要创建索引,数据库就会使用它

这里是

-- sample table, without the index
create table mytable(id int, created_at datetime);

--  the query does a full scan, as no index is available
explain select created_at from mytable where created_at >= '2020-05-15 23:00:00';
id |选择|类型|表格|分区|类型|可能的|键|键|列|参考|行|过滤|额外 -: | :---------- | :------ | :--------- | :---- | :--------------------- | :--------------------- | :------ | :--- | ---: | -------: | :----------------------- 1 |简单|我的表格| null |索引| idx | U我的表格|创建| idx | U我的表格|创建| 6 | null | 1 | 100.00 |使用where;使用索引
如果这些值均匀分布,大约25%的行是
='2020-05-15 23:00:00'
是的,Mysql将更喜欢使用完整的表扫描,而不是使用索引,因为您需要的表占很大比例

日期
上下文中,
日期('2020-05-15 23:00:00')
'2020-05-15'
相同

DATETIME
上下文中,
DATETIME('2020-05-15 23:00:00')
'2020-05-15 23:00:00'相同

使用索引
意味着
索引
是“覆盖”的,这意味着整个查询可以完全在索引的BTree中执行,而无需到达数据的BTree


使用索引条件
意味着完全不同的事情——它与MySQL设计中的两层(“处理程序”和“引擎”)相关的轻微优化有关。(更多详细信息请参见“ICP”又名“索引条件下推”。

请为您的表格共享
show create table
的输出。@GMB这是什么意思?我是如何创建表的?只需运行
show create[tablename]
谢谢您的回答。我没有看到show create table查询的最后一部分。它似乎有一个索引,请参见上面的编辑版本。当MySQL判断它比使用索引更有效时,我认为它使用了全表扫描。
-- now add the index
create index idx_mytable_created_at on mytable(created_at);

-- the query uses the index
explain select created_at from mytable where created_at >= '2020-05-15 23:00:00';
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra -: | :---------- | :------ | :--------- | :---- | :--------------------- | :--------------------- | :------ | :--- | ---: | -------: | :----------------------- 1 | SIMPLE | mytable | null | index | idx_mytable_created_at | idx_mytable_created_at | 6 | null | 1 | 100.00 | Using where; Using index