2015-05-28 152 views
0

模式是這樣的visits_table是否可以優化這些查詢?

+---------------------------+----------------------+------+-----+---------+----------------+ 
| Field      | Type     | Null | Key | Default | Extra   | 
+---------------------------+----------------------+------+-----+---------+----------------+ 
| idvisit     | int(10) unsigned  | NO | PRI | NULL | auto_increment | 
| idsite     | int(10) unsigned  | NO | MUL | NULL |    | 
| idvisitor     | binary(8)   | NO |  | NULL |    | 
| visit_time    | datetime    | NO |  | NULL |    | 
| user_id     | varchar(200)   | YES |  | NULL |    | 
| config_cookie    | tinyint(1)   | NO |  | NULL |    | 
| custom_var_k1    | varchar(200)   | YES |  | NULL |    | 
| custom_var_v1    | varchar(200)   | YES |  | NULL |    | 
+---------------------------+----------------------+------+-----+---------+----------------+ 

索引:

+----------------------+------------+------------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table    | Non_unique | Key_name      | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+----------------------+------------+------------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| visits_table   |   0 | PRIMARY      |   1 | idvisit    | A   |  1502 | NULL  | NULL |  | BTREE  |   |    | 
| visits_table   |   1 | index_idsite_datetime  |   1 | idsite     | A   |   5 | NULL  | NULL |  | BTREE  |   |    | 
| visits_table   |   1 | index_idsite_datetime  |   2 | visit_time    | A   |  1502 | NULL  | NULL |  | BTREE  |   |    | 
| visits_table   |   1 | index_idsite_idvisitor  |   1 | idsite     | A   |   1 | NULL  | NULL |  | BTREE  |   |    | 
| visits_table   |   1 | index_idsite_idvisitor  |   2 | idvisitor    | A   |   500 | NULL  | NULL |  | BTREE  |   |    | 
+----------------------+------------+------------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

,我已經準備了兩個查詢:

SELECT 
    COUNT(`idvisit`) AS `visits_count`, 
    DATE(`visit_time`) AS `date` 
FROM (
    SELECT * 
    FROM 
     `visits_table` 
    WHERE 
     `idsite` = 2 
     AND `visit_time` >= '2015-04-01 00:00:00' 
     AND `visit_time` <= '2015-04-30 23:59:59' 
) AS `visits` 
WHERE 1 
GROUP BY 
    DATE(`visit_time`); 



+----+-------------+----------------------+------+----------------------------------------------+------+---------+------+------+---------------------------------+ 
| id | select_type | table    | type | possible_keys        | key | key_len | ref | rows | Extra       | 
+----+-------------+----------------------+------+----------------------------------------------+------+---------+------+------+---------------------------------+ 
| 1 | PRIMARY  | <derived2>   | ALL | NULL           | NULL | NULL | NULL | 1469 | Using temporary; Using filesort | 
| 2 | DERIVED  | visits_table   | ALL | index_idsite_datetime,index_idsite_idvisitor | NULL | NULL | NULL | 1502 | Using where      | 
+----+-------------+----------------------+------+----------------------------------------------+------+---------+------+------+---------------------------------+ 
在MySQL 5.6

行2型= ref時,鍵= index_idsite_datetime,key_len = 4,ref = const,Extra =使用索引

SELECT 
     COUNT(`idvisit`) AS `visits_count`, 
     DATE(`visit_time`) AS `date` 
    FROM 
     `visits_table` 
    WHERE 
     `idsite` = 2 
     AND `visit_time` >= '2015-04-01 00:00:00' 
     AND `visit_time` <= '2015-04-30 23:59:59' 
    GROUP BY 
     DATE(`visit_time`); 

+----+-------------+----------------------+-------+----------------------------------------------+-----------------------+---------+------+------+-----------------------------------------------------------+ 
| id | select_type | table    | type | possible_keys        | key     | key_len | ref | rows | Extra              | 
+----+-------------+----------------------+-------+----------------------------------------------+-----------------------+---------+------+------+-----------------------------------------------------------+ 
| 1 | SIMPLE  | visits_table   | range | index_idsite_datetime,index_idsite_idvisitor | index_idsite_datetime | 12  | NULL | 1468 | Using where; Using index; Using temporary; Using filesort | 
+----+-------------+----------------------+-------+----------------------------------------------+-----------------------+---------+------+------+-----------------------------------------------------------+ 

我有86M行的表和兩個查詢需要約2小時執行。有什麼我可以做的,以加快這些查詢?

+0

我認爲問題是強制MYSQL排序結果(filesort)的GROUP BY DATE(...)。如果您可以將Visit_time分隔爲Visit_Date和Visit_Time,則您的查詢速度會更快。你有多少內存和多少符合條件的結果(在分組之前)? – Tim3880

+0

嘗試運行['ANALYZE TABLE VISITS_TABLE'](https://dev.mysql.com/doc/refman/5.0/en/analyze-table.html),然後重試第二個查詢。此外,將語法更改爲'AND visit_time BETWEEN'2015-04-01 00:00:00'AND'2015-04-30 23:59:59'' – Bohemian

回答

1

我建議編寫查詢作爲:

SELECT COUNT(*) AS `visits_count`, 
     DATE(`visit_time`) AS `date` 
FROM `visits_table` 
WHERE `idsite` = 2 AND 
     `visit_time` >= '2015-04-01' AND 
     `visit_time` < '2015-05-01' 
GROUP BY DATE(`visit_time`); 

這可能節省大量的時間絲毫,因爲指數現在是一個覆蓋索引。

我認爲改善查詢的一種方法是擺脫group by。嘗試這樣的查詢:

select dte, 
     (select count(*) 
     from visits_table 
     where idsite = 2 and 
       visit_time >= dates.dte AND visit_time < dates.dte + interval 1 day 
from (select date('2015-04-01') as dte union all 
     select date('2015-04-02') as dte 
    ) dates; 

MySQL是如何使用索引相關子查詢遠勝它是關於使用索引聚集。這種方法的缺點是時間會隨着結果集中天數的增加而線性增加。

+0

您是否意味着工會每天都像日復一日?像這樣select?(select date('2015-04-01')as dte union all select date('2015-04-02')as dte(...)union all select date('2015-04-30 「))。所以我會結合所有的日子?這將是29個工會會不會很慢? –

+0

@ SebastianPiskorski。 。 。是。我只是從兩天開始。做30個常量記錄的聯合基本上沒有時間在查詢的上下文中。問題是相關的子查詢,您可以在更短的時間內進行測試。 –