![](/img/trans.png)
[英]Why 'select * from Employee group by Id' is much faster than directly use the Employee table?
[英]Why is COUNT() query from large table much faster than SUM()
我有一个带有下表的数据仓库:
主要
约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条记录,并且具有以下字段
顾客
大约有23,000条记录,以下文件
以下查询运行非常快(不到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 |
提前致谢!
编辑
所有表都表明它正在使用Engine InnoDB
另外,请注意,如果我只是执行“ SELECT *”查询,则运行速度非常快(不到2秒)。 我希望'SUM()'不应该花更长的时间,因为SELECT *无论如何都必须检索行...
解决了
这是我所学到的:
谢谢大家!
索引是键行的列表。
当您执行count()
查询时,可以忽略数据库中的实际数据,而只使用索引。
当您执行sum(sales)
查询时,必须从磁盘读取每一行以获取销售数据,因此要慢得多。
此外,可以批量读取索引,然后在内存中进行处理,而磁盘访问将随机破坏驱动器,以尝试从磁盘读取行。
最后,索引本身可能具有计数汇总(以帮助计划生成)
您的表上实际上有三个索引:
PRIMARY KEY (`id`),
KEY `idx_pci` (`pid`,`cid`,`iid`) USING HASH,
KEY `idx_pic` (`pid`,`iid`,`cid`) USING HASH
因此,您仅在id
, pid
, cid
, iid
列上具有索引。 (顺便说一句,大多数数据库足够聪明,可以组合索引,因此您可能可以对索引进行一些优化)
如果您添加了其他键(例如KEY idx_sales(id,sales)
可以提高性能,但是鉴于销售值可能会以数字形式分配,那么您将为更新添加额外的性能成本,这可能是一件坏事
简单的答案是count()
仅对行进行计数。 这可以通过索引来满足。
sum()
需要标识每一行,然后获取页面以获取sales
列。 这增加了很多开销-每行大约加载一页。
如果将sales
添加到索引中,那么它也应该非常快,因为它不必获取原始数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.