2014-11-05 117 views
1

我有一个MySQL 5.5表,看起来像这样;为什么主键比索引快?

CREATE TABLE `date_test` (
    `id` int(11) NOT NULL DEFAULT '0', 
    `report_date` datetime NOT NULL, 
    `module_id` int(11) NOT NULL, 
    `country_id` int(11) NOT NULL, 
    `clicks` int(11) DEFAULT '0' 
    PRIMARY KEY (`id`,`report_date`,`module_id`,`country_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

它只有一个PK,没有索引。运行一个简单的SELECT查询;

select count(*) from date_test 
where report_date between'2014-09-01' and '2014-09-15' 

这需要1.1秒,返回809349条记录。

现在,我在report_date上添加一个索引,尝试加快速度;

ALTER TABLE `date_test` 
ADD INDEX `report_date` (`report_date` ASC); 

我的SELECT COUNT(*)查询现在只需2.6秒运行。我的问题;如何将此字段作为索引影响查询性能?

添加EXPLAIN;

With Index and PK (2.6 seconds) 
id   1 
select_type SIMPLE  
table   date_test 
type   range 
possible_keys report_date 
key   report_date 
key_len  8 
ref  
rows   792170  
Extra   Using where; Using index  

With PK only, no Index (1.1 seconds) 
id   1 
select_type SIMPLE  
table   date_test 
type   index 
possible_keys  
key   PRIMARY 
key_len  1048  
ref  
rows   1584341 
Extra   Using where; Using index  

With no Index or PK (1.4 seconds)  
id   1 
select_type SIMPLE  
table   date_test 
type   ALL 
possible_keys  
key  
key_len  
ref  
rows   1652883 
Extra   Using where 
+0

为什么你坚持这么多列到PK? – 2014-11-05 16:14:31

+1

尝试检查date_test中的_select count(*) where '2014-09-01 00:00:00'和'2014-09-15 23:59:59'之间的report_date,以确保日期之间没有转换涉及日期时间。 – Kickstart 2014-11-05 16:35:54

+0

向查询添加时间似乎不会提高性能,它必须在日期中隐式添加'00:00:00'。 – 2014-11-05 17:36:42

回答

1

看看EXPLAIN <YOUR_QUERY>的结果。我的猜测是(没有足够的信息可以确定)MySQL现在正在使用索引,并且错误地猜测使用索引会更快。

如果索引覆盖的行很多,那么只需执行表扫描就可以更快。索引在查询时会增加一些开销,因此,如果between覆盖表中的行的80%以上(完全是任意的,但您明白了),则表扫描可能会更快。

看该查询的输出以获得一个想法:

SELECT report_date between '2014-09-01' and '2014-09-15', COUNT(*) FROM date_Test 
GROUP BY report_date between '2014-09-01' and '2014-09-15' 
+0

我已经为三个查询中的每一个添加了我的EXPLAIN。我认为你对MySQL挑选'错误'索引的观察适用于此。 – 2014-11-05 15:57:29

相关问题