![](/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.