索引日期字段mysql

时间:2017-09-10 16:42:50

标签: mysql sql indexing

我有一个包含3个字段的表格截图:

CREATE TABLE `screenshot` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `UserID` int(11) NOT NULL,
  `DateTaken` date NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `DateTaken` (`DateTaken`),
  KEY `UserID` (`UserID`) USING BTREE,
  CONSTRAINT `userID_foreign_key` FOREIGN KEY (`UserID`) REFERENCES `users` (`UserID`)
) ENGINE=InnoDB AUTO_INCREMENT=22514871 DEFAULT CHARSET=latin1

SELECT @@innodb_buffer_pool_size

结果:1​​6777216

查询:

SELECT COUNT(ID) total
        FROM screenshot WHERE DateTaken BETWEEN '2000-05-01' AND '2000-06-10'

结果:2828844

解释输出:

ID|select_type|   table  |type |possible_keys|   key   |key_len| rows  |Extra
1 |  SIMPLE   |screenshot|range|  DateTaken  |DateTaken|  3    |5730138|Using where; Using index

这是我的问题: 我已将索引添加到DateTaken列,但扫描行(Explain输出)大于结果。它看起来像是一个完整的扫描表。查询的查询运行时间为15秒。如何提高上述查询的速度?

3 个答案:

答案 0 :(得分:1)

没有问题。你的指数没问题。解释......

5730138中的EXPLAIN估算值。它可以大于或小于实际值,有时是大量的。不要被它打扰。

在该日期范围内有2.8M的屏幕截图,对吗?好吧,扫描索引可能需要15秒来计算那么多行。

如果您想进一步分析,请提供:
RAM大小
innodb_buffer_pool_size
SHOW CREATE TABLE screenshot;(这将显示引擎)
桌子有多大(GB)
你有什么类型的磁盘(旋转与SSD)

有了这些,我们可以进一步讨论缓存,I / O和引擎的影响。它可能有助于解释" 15秒"与" 20"。

(并且,是的,请使用COUNT(*),而不是COUNT(x),除非您需要测试x是否为NULL。)

如果你使用InnoDB,那么INDEX(DateTaken, id)INDEX(DateTaken)相同,所以我建议你急于接受这个答案。

缓冲池

innodb_buffer_pool_size应设置为大约70%的RAM。你拥有的是如此之小(旧的16M默认值),即使建议的索引也不适合缓存。因此,查询将始终击中磁盘,至少在某些时候。增加缓冲池应该可以显着提高速度,可能低至2秒。

答案 1 :(得分:0)

尝试运行此查询:

SELECT COUNT(*) as total
FROM screenshot
WHERE DateTaken BETWEEN '2000-05-01' AND '2000-06-10';

ID中对SELECT的引用可能会影响索引的使用。

答案 2 :(得分:0)

您可以尝试添加复合索引

  create index test on screenshot (DateTaken, id)