我有一个包含以下表格的数据仓库:
主要的
约 800 万条记录
CREATE TABLE `main` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cid` mediumint(8) unsigned DEFAULT NULL, //This is the customer id
`iid` mediumint(8) unsigned DEFAULT NULL, //This is the item id
`pid` tinyint(3) unsigned DEFAULT NULL, //This is the period id
`qty` double DEFAULT NULL,
`sales` double DEFAULT NULL,
`gm` double DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_pci` (`pid`,`cid`,`iid`) USING HASH,
KEY `idx_pic` (`pid`,`iid`,`cid`) USING HASH
) ENGINE=InnoDB AUTO_INCREMENT=7978349 DEFAULT CHARSET=latin1
时期
该表大约有 50 条记录,并具有以下字段
- ID
- 月
- 年
顾客
这有大约 23,000 条记录和以下文件
- ID
- number //这个字段是唯一的
- name //这只是一个描述字段
以下查询运行速度非常快(不到 1 秒)并返回大约 2,000:
select count(*)
from mydb.main m
INNER JOIN mydb.period p ON p.id = m.pid
INNER JOIN mydb.customer c ON c.id = m.cid
WHERE p.year = 2013 AND c.number = 'ABC';
但是这个查询要慢得多(超过 45 秒),这与前面的相同,但求和而不是计数:
select sum(sales)
from mydb.main m
INNER JOIN mydb.period p ON p.id = m.pid
INNER JOIN mydb.customer c ON c.id = m.cid
WHERE p.year = 2013 AND c.number = 'ABC';
当我解释每个查询时,我看到的唯一区别是,在“count()”查询中,“Extra”字段显示“Using index”,而对于“sum()”查询,该字段为 NULL。
解释 count() 查询
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | c | const | PRIMARY,idx_customer | idx_customer | 11 | const | 1 | Using index |
| 1 | SIMPLE | p | ref | PRIMARY,idx_period | idx_period | 4 | const | 6 | Using index |
| 1 | SIMPLE | m | ref | idx_pci,idx_pic | idx_pci | 6 | mydb.p.id,const | 7 | Using index |
解释 sum() 查询
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | c | const | PRIMARY,idx_customer | idx_customer | 11 | const | 1 | Using index |
| 1 | SIMPLE | p | ref | PRIMARY,idx_period | idx_period | 4 | const | 6 | Using index |
| 1 | SIMPLE | m | ref | idx_pci,idx_pic | idx_pci | 6 | mydb.p.id,const | 7 | NULL |
- 为什么 count() 比 sum() 快这么多?不应该对两者都使用索引吗?
- 我该怎么做才能使 sum() 更快?
提前致谢!
编辑
所有表都显示它正在使用 Engine InnoDB
另外,作为旁注,如果我只是执行“SELECT *”查询,它会运行得非常快(不到 2 秒)。我希望'SUM()'不应该花费比这更长的时间,因为 SELECT * 无论如何都必须检索行......
解决了
这是我学到的:
- 由于销售字段不是索引的一部分,它必须从硬盘驱动器中检索记录(这可能很慢)。
- 我对此不太熟悉,但看起来 I/O 性能可以通过切换到 SSD(固态驱动器)来提高。我将不得不对此进行更多研究。
现在,我想我将创建另一层摘要以获得我正在寻找的性能。- 我将主表上的索引重新定义为 (pid,cid,iid,sales,gm,qty),现在 sum() 查询运行得非常快!
谢谢大家!