2012-12-09 112 views
4

表結構:MySQL查詢運行得更快

CREATE TABLE IF NOT EXISTS `logs` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `user` bigint(20) unsigned NOT NULL, 
    `type` tinyint(1) unsigned NOT NULL, 
    `date` int(11) unsigned NOT NULL, 
    `plus` decimal(10,2) unsigned NOT NULL, 
    `minus` decimal(10,2) unsigned NOT NULL, 
    `tax` decimal(10,2) unsigned NOT NULL, 
    `item` bigint(20) unsigned NOT NULL, 
    `info` char(10) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `item` (`item`), 
    KEY `user` (`user`), 
    KEY `type` (`type`), 
    KEY `date` (`date`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0 ROW_FORMAT=FIXED; 

查詢:

SELECT logs.item, COUNT(logs.item) AS total FROM logs WHERE logs.type = 4 GROUP BY logs.item; 

表保持110K記錄哪些50K型4記錄。 執行時間:0.13秒

我知道這很快,但我可以讓它更快嗎?

我期待100萬條記錄,因此時間會增長很多。

+1

您可以優化與索引你的代碼檢查此鏈接http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html –

+0

爲u可以在表模式看我已經添加了索引。 – transilvlad

回答

4

與EXPLAIN分析查詢:

mysql> EXPLAIN SELECT logs.item, COUNT(logs.item) AS total FROM logs 
    WHERE logs.type = 4 GROUP BY logs.item\G 

      id: 1 
    select_type: SIMPLE 
     table: logs 
     type: ref 
possible_keys: type 
      key: type 
     key_len: 1 
      ref: const 
     rows: 1 
     Extra: Using where; Using temporary; Using filesort 

「使用臨時;使用文件排序」 表示一些昂貴的操作。因爲優化器知道它不能依靠存儲在一起的每個值item的行,所以它需要掃描整個表並收集臨時表中每個不同項目的計數。然後對產生的臨時表進行排序以產生結果。

您需要按照該順序在列(類型,項目)上的日誌表上建立索引。然後,優化器知道它可以充分利用索引樹在轉到下一個值之前完全掃描logs.item的每個值。通過這樣做,它可以跳過臨時表來收集值,並跳過結果的隱式排序。

mysql> CREATE INDEX logs_type_item ON logs (type,item); 

mysql> EXPLAIN SELECT logs.item, COUNT(logs.item) AS total FROM logs 
    WHERE logs.type = 4 GROUP BY logs.item\G 

      id: 1 
    select_type: SIMPLE 
     table: logs 
     type: ref 
possible_keys: type,logs_type_item 
      key: logs_type_item 
     key_len: 1 
      ref: const 
     rows: 1 
     Extra: Using where 
+0

在某些mysql版本中,'COUNT(*)'比'COUNT(column)'更快嗎? (沒有關於索引的爭論,你有我的+1)。 –

+0

@ypercube,是的,COUNT(*)比MySQL中的COUNT(expr)稍快。但與這個查詢的重大改進相比,這種差異是微不足道的,即消除臨時表。 –

+0

完美答案。謝謝。 – transilvlad