Mysql 在where子句中使用datetime索引
我有一个有2亿行的表,其中索引是在“created_at”列中创建的,该列是datetime数据类型 显示创建表[tablename]输出: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
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