我有下一张桌子:
CREATE TABLE `test` (
`fingerprint` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
`country` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`loader` int(10) unsigned NOT NULL,
`date` date NOT NULL,
`installer` int(10) unsigned DEFAULT NULL,
`browser` varchar(5) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`version` varchar(5) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`os` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`language` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`fingerprint`, `date`),
KEY `date_1` (`date`),
KEY `date_2` (`date`,`loader`,`installer`,`country`,`browser`,`os`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
现在它包含10M记录,并且每天将增加2M记录。
我的问题,为什么MySQL在下一个查询中使用“使用位置”:
explain select count(*) from test where date between '2013-08-01' and '2013-08-10'
1 SIMPLE test range date_1,date_2 date_1 3 1601644 Using where; Using index
更新,为什么下一个问题有类型 - 全部和使用在哪里:
explain select * from test use key(date_1) where date between '2013-08-01' and '2013-08-10'
1 SIMPLE test ALL date_1 null null null 3648813 Using where
答案 0 :(得分:1)
使用索引。
它就是这么说的:Using where; Using index
。 “使用位置”并不意味着完全扫描,这意味着它使用了您提供的WHERE
条件。
1601644号码也暗示:它意味着它预计会读取大约160万条记录,而不是表中的整个10M记录,而且它与您的~2M /天估计相关。
简而言之,它似乎表现不错,只会检索很多数据。
但是,当索引看起来足够时,它也会读取表格数据。尝试使用count(*)
更改count(date)
,因此date
是整个查询中提到的唯一字段。如果您只获得Using index
,那么它可能会更快。
答案 1 :(得分:0)
您的查询不仅仅是“使用位置”,它实际上是“使用位置;使用索引”。这意味着该索引用于匹配您的WHERE
条件和,该索引用于执行键值的查找。这是最好的情况,因为实际上从未扫描过表,只能使用索引处理查询。
Here you can find完整描述了您正在查看的输出的含义。
您的第二个查询仅显示“使用位置”通知。这意味着索引仅用于过滤行。必须从表中读取数据(没有“使用索引”通知),因为索引不包含所有行数据(您选择了所有列,但所选索引仅涵盖date
)。如果您有覆盖索引(涵盖所有列),则可能会使用此索引。