2016-04-04 137 views
2

這是我的表:優化MySQL查詢日期組

CREATE TABLE IF NOT EXISTS `test_dates` (
    `date` date NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `test_log` (
    `id` int(10) unsigned NOT NULL, 
    `timest` datetime NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE `test_dates` 
    ADD PRIMARY KEY (`date`); 

ALTER TABLE `test_log` 
    ADD PRIMARY KEY (`id`), 
    ADD KEY `emissione` (`timest`); 

我有這樣的查詢計算每個日期的日誌:

SELECT d.date, COUNT(l.id) 
FROM test_dates d 
LEFT JOIN test_log l ON l.timest>=d.date AND l.timest<d.date + INTERVAL 1 DAY 
GROUP BY d.date 

test_dates日期科拉姆和test_log被索引表在索引時間列索引。

但解釋這個查詢我得到了查詢類型「ALL」和NULL鍵。

+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered |      Extra      | | 
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 
| 1 | SIMPLE  | d  | NULL  | index | PRIMARY  | PRIMARY | 3  | NULL | 705 | 100.00 | Using index         | | 
| 1 | SIMPLE  | l  | NULL  | ALL | emissione  | NULL  | NULL  | NULL | 98256 | 100.00 | Range checked for each record (index map: 0x2) | | 
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 

爲什麼mysql不能使用表索引?

日誌表有大約100000行,查詢速度很慢。

+0

推測查詢速度很慢?至少,有關查詢性能的問題需要所有相關表(最好是樣本數據)的CREATE語句以及EXPLAIN的結果。 – Strawberry

+0

好吧,我正在更新它。 – Tobia

回答

2

嘗試運行這是一個相關子查詢:使用帶有GROUP BY索引時

SELECT d.date, 
     (SELECT COUNT(l.id) 
     FROM log l 
     WHERE l.timest >= d.date AND l.timest < d.date + INTERVAL 1 DAY 
     ) as cnt 
FROM dates d; 

MySQL是不是很好。有時使用子查詢可以顯着提升性能。你的表格有正確的索引。

+0

我試了一下,但沒有明顯的性能提升... – Tobia

+0

工作測試(MySQL 5.6.26):沒有區別。在家測試(MariaDB 10.0.19):巨大的差異。也許MySQL 5.7和MariaDB 10一樣好。 –

+0

我確認我用MySQL 5.6.26測試了它 – Tobia

0

如果索引和相關的子查詢不適合您,您最好的選擇可能是更新日期表並添加彙總計數列。然後,當您向日志表中插入數據時,將在該日期的日期表中爲您的計數器添加1。如果還沒有這樣的記錄,則添加一個並將其計數設置爲1,因爲它是新記錄。

然後,您需要做的就是根據日期範圍從日期表中選擇一個總和(),而不再查看詳細信息。一旦選定給定日期進行可能的審查,那麼您可以查詢基礎數據。

0

轉過身去。在第二個表先做一個高效GROUP BY(見子查詢,下同),然後在缺少天補(外部查詢):

SELECT date, 
     IFNULL(log.ct, 0) AS ct 
    FROM 
     (SELECT DATE(timest) AS date, 
       COUNT(*) AS ct 
      FROM test_log 
      GROUP BY date 
    ) AS log 
    RIGHT JOIN test_dates AS d USING(date); 

如果要限制的日期範圍內,添加WHERE條款均子查詢和外部查詢。