如何在DATETIME字段的日期部分创建索引?
mysql> SHOW COLUMNS FROM transactionlist;
+-------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------+----------------+
| TransactionNumber | int(10) unsigned | NO | PRI | NULL | auto_increment |
| WagerId | int(11) | YES | MUL | 0 | |
| TranNum | int(11) | YES | MUL | 0 | |
| TranDateTime | datetime | NO | | NULL | |
| Amount | double | YES | | 0 | |
| Action | smallint(6) | YES | | 0 | |
| Uid | int(11) | YES | | 1 | |
| AuthId | int(11) | YES | | 1 | |
+-------------------+------------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
TranDateTime用于在事件发生时保存事务的日期和时间
我的表中有超过1,000,000条记录和声明
SELECT * FROM transactionlist where date(TranDateTime) = '2008-08-17'
Run Code Online (Sandbox Code Playgroud)
需要很长的时间.
编辑:
看一下这篇关于" 为什么MySQL的DATETIME可以而且应该避免 "的博客文章
Mic*_*son 63
如果我没记错的话,那将会运行一个完整的表扫描,因为你正在通过一个函数传递列.MySQL将乖乖地为每一列运行该函数,绕过索引,因为查询优化器无法真正知道函数的结果.
我会做的是:
SELECT * FROM transactionlist
WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-17 23:59:59.999999';
Run Code Online (Sandbox Code Playgroud)
这应该会给你2008-08-17发生的一切.
您无法仅在日期部分创建索引.你有什么理由吗?
即使您可以仅在日期部分创建索引,优化器也可能仍然不会将其用于上述查询.
我想你会发现的
SELECT * FROM transactionlist WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-18'
Run Code Online (Sandbox Code Playgroud)
是有效的,做你想要的.
另一个选项(与5.7.3及更高版本相关)是基于datetime列创建生成/虚拟列,然后对其进行索引.
CREATE TABLE `table` (
`my_datetime` datetime NOT NULL,
`my_date` varchar(12) GENERATED ALWAYS AS (DATE(`my_daetime`)) STORED,
KEY `my_idx` (`my_date`)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)
我不知道 mySql 的具体情况,但是只对整个日期字段建立索引有什么害处?
然后只需搜索:
select * from translist
where TranDateTime > '2008-08-16 23:59:59'
and TranDateTime < '2008-08-18 00:00:00'
Run Code Online (Sandbox Code Playgroud)
如果索引是 b 树或其他合理的索引,那么应该很快就能找到它们。