2013-01-04 110 views
0

我需要你的幫助,優化查詢。一個表是一個有數百萬條目的日誌表,我試圖將我的查詢分解爲< 1。我的查詢應該給出一個全面的概述,因此應該很快。我確信我可以在腳本的幫助下對列表進行多個簡單查詢。但是,腳本可以做什麼,我可以認爲 - 我希望至少。也許並不是所有的部分都是最好的,但是我被困在一個使臨時表和文件夾(我發現真的很糟糕)的查詢中。隨着閱讀周圍我發現使用一些整潔和良好的索引,但現在我卡在一個特定的點。MySQL查詢優化,大表,使用臨時filesort

讓我告訴你它的結果我的最終查詢:

SELECT 
    ps.SERVER_ID, 
    ps.FULLNAME, 
    SUM(CASE WHEN pml.ID_TYPE = 3 THEN 1 ELSE 0 END) 'amount_warning', 
    SUM(CASE WHEN pml.ID_TYPE = 4 THEN 1 ELSE 0 END) 'amount_error', 
    SUM(CASE WHEN pml.ID_TYPE = 5 THEN 1 ELSE 0 END) 'amount_alert', 
    SUM(CASE WHEN pml.ID_TYPE = 7 THEN 1 ELSE 0 END) 'amount_critical' 
FROM 
    PAR_SERVER ps 
INNER JOIN 
    PAR_MONITORINGv2_LOG pml ON ps.SERVER_ID = pml.SERVER_ID 
WHERE 
    pml.CREATED_DATE > date_sub(NOW() , INTERVAL 7 DAY) 
GROUP BY 
    ps.SERVER_ID; 

這裏是我所得到的:

mysql> [thequeryabove] 
[...] 
59 rows in set (11.69 sec) 

mysql> explain [thequeryabove] 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref      | rows | Extra          | 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
| 1 | SIMPLE  | pml | ALL | SERVER_ID,SERVER_ID-ID_TYPE | NULL | NULL | NULL      | 4014447 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | ps | eq_ref | PRIMARY      | PRIMARY | 4  | database.pml.SERVER_ID |  1 |            | 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
2 rows in set (0.00 sec) 

這是我當前的表設置:

mysql> describe PAR_SERVER; 
+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| SERVER_ID  | int(255)  | NO | PRI | NULL | auto_increment | 
| FULLNAME  | varchar(255) | YES |  | NULL |    | 
| SHORTNAME  | varchar(255) | YES | MUL | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 
3 rows in set (0.00 sec) 

mysql> show indexes from PAR_SERVER; 
+------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| PAR_SERVER |   0 | PRIMARY |   1 | SERVER_ID | A   |   142 |  NULL | NULL |  | BTREE  |   | 
| PAR_SERVER |   1 | shortname |   1 | SHORTNAME | A   |   142 |  NULL | NULL | YES | BTREE  |   | 
+------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
2 rows in set (0.00 sec) 

mysql> select count(*) from PAR_SERVER; 
+----------+ 
| count(*) | 
+----------+ 
|  142 | 
+----------+ 
1 row in set (0.00 sec) 

mysql> describe PAR_MONITORINGv2_LOG; 
+--------------+----------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+--------------+----------+------+-----+---------+----------------+ 
| ID   | int(11) | NO | PRI | NULL | auto_increment | 
| ID_TYPE  | int(11) | NO | MUL | NULL |    | 
| ID_SERVICE | int(11) | NO | MUL | NULL |    | 
| SERVER_ID | int(11) | NO | MUL | NULL |    | 
| MESSAGE  | tinytext | NO |  | NULL |    | 
| CREATED_DATE | datetime | NO |  | NULL |    | 
+--------------+----------+------+-----+---------+----------------+ 
6 rows in set (0.00 sec) 

mysql> show indexes from PAR_MONITORINGv2_LOG; 
+----------------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table    | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+----------------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| PAR_MONITORINGv2_LOG |   0 | PRIMARY   |   1 | ID   | A   |  3998188 |  NULL | NULL |  | BTREE  |   | 
| PAR_MONITORINGv2_LOG |   1 | ID_TYPE   |   1 | ID_TYPE  | A   |   7 |  NULL | NULL |  | BTREE  |   | 
| PAR_MONITORINGv2_LOG |   1 | ID_SERVICE  |   1 | ID_SERVICE | A   |   5 |  NULL | NULL |  | BTREE  |   | 
| PAR_MONITORINGv2_LOG |   1 | SERVER_ID   |   1 | SERVER_ID | A   |   66 |  NULL | NULL |  | BTREE  |   | 
| PAR_MONITORINGv2_LOG |   1 | SERVER_ID-ID_TYPE |   1 | SERVER_ID | A   |   66 |  NULL | NULL |  | BTREE  |   | 
| PAR_MONITORINGv2_LOG |   1 | SERVER_ID-ID_TYPE |   2 | ID_TYPE  | A   |   258 |  NULL | NULL |  | BTREE  |   | 
+----------------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
6 rows in set (0.00 sec) 

mysql> select count(*) from PAR_MONITORINGv2_LOG; 
+----------+ 
| count(*) | 
+----------+ 
| 3998386 | 
+----------+ 
1 row in set (0.00 sec) 

這裏有時間結果一步一步打破我的查詢。固定每個部分花費這麼長時間後,我可能會逐步加深。但是現在只有運行時間爲2.30秒的查詢目前對這個問題很有意思。

mysql> SELECT ps.SERVER_ID, ps.FULLNAME FROM PAR_SERVER ps INNER JOIN PAR_MONITORINGv2_LOG pml ON ps.SERVER_ID = pml.SERVER_ID WHERE pml.CREATED_DATE > date_sub(NOW() , INTERVAL 7 DAY) GROUP BY ps.SERVER_ID; 
[...] 
59 rows in set (6.41 sec) 

mysql> explain [thequeryabove] 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref      | rows | Extra          | 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
| 1 | SIMPLE  | pml | ALL | SERVER_ID,SERVER_ID-ID_TYPE | NULL | NULL | NULL      | 4014788 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | ps | eq_ref | PRIMARY      | PRIMARY | 4  | database.pml.SERVER_ID |  1 |            | 
+----+-------------+-------+--------+-----------------------------+---------+---------+---------------------------+---------+----------------------------------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT ps.SERVER_ID, ps.FULLNAME FROM PAR_SERVER ps INNER JOIN PAR_MONITORINGv2_LOG pml ON ps.SERVER_ID = pml.SERVER_ID GROUP BY ps.SERVER_ID; 
[...] 
59 rows in set (2.30 sec) 

mysql> explain [thequeryabove] 
+----+-------------+-------+--------+-----------------------------+-----------+---------+---------------------------+---------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref      | rows | Extra          | 
+----+-------------+-------+--------+-----------------------------+-----------+---------+---------------------------+---------+----------------------------------------------+ 
| 1 | SIMPLE  | pml | index | SERVER_ID,SERVER_ID-ID_TYPE | SERVER_ID | 4  | NULL      | 4015694 | Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | ps | eq_ref | PRIMARY      | PRIMARY | 4  | database.pml.SERVER_ID |  1 |            | 
+----+-------------+-------+--------+-----------------------------+-----------+---------+---------------------------+---------+----------------------------------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT pml.SERVER_ID FROM PAR_MONITORINGv2_LOG pml GROUP BY pml.SERVER_ID; 
[...] 
65 rows in set (0.00 sec) 

mysql> explain [thequeryabove] 
+----+-------------+-------+-------+---------------+-----------+---------+------+------+--------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra     | 
+----+-------------+-------+-------+---------------+-----------+---------+------+------+--------------------------+ 
| 1 | SIMPLE  | pml | range | NULL   | SERVER_ID | 4  | NULL | 67 | Using index for group-by | 
+----+-------------+-------+-------+---------------+-----------+---------+------+------+--------------------------+ 
1 row in set (0.00 sec) 

我能夠通過定義(SERVER_ID,ID_TYPE)指數爲我下面的例子查詢來提高查詢了很多證實:

mysql> SELECT count(*) 'count_warnings' FROM PAR_MONITORINGv2_LOG pml WHERE pml.SERVER_ID = 191 AND pml.ID_TYPE = 3 GROUP BY pml.SERVER_ID; 
[...] 
1 row in set (0.01 sec) 

mysql> explain [thequeryabove] 
+----+-------------+-------+------+-------------------------------------+-------------------+---------+-------------+-------+-------------+ 
| id | select_type | table | type | possible_keys      | key    | key_len | ref   | rows | Extra  | 
+----+-------------+-------+------+-------------------------------------+-------------------+---------+-------------+-------+-------------+ 
| 1 | SIMPLE  | pml | ref | ID_TYPE,SERVER_ID,SERVER_ID-ID_TYPE | SERVER_ID-ID_TYPE | 8  | const,const | 10254 | Using index | 
+----+-------------+-------+------+-------------------------------------+-------------------+---------+-------------+-------+-------------+ 
1 row in set (0.00 sec) 

我現在被困在最broked下來查詢的執行時間很長,爲2.30秒。我不知道如何使用沒有任何where子句的查詢的索引。

+0

A'使用filesort'不一定是「非常糟糕」;但對於大型設備,排序操作可能會對性能產生重大影響。有時,當適當的索引可用時,MySQL可以避免排序操作。可以使用覆蓋索引的訪問計劃('使用索引')通常會提高性能。 – spencer7593

回答

1

您的查詢一定會從PAR_MONITORINGv2_LOG(CREATED_DATE,SERVER_ID,ID_TYPE)加入綜合指數受益最大。不過,我建議即使是簡單的索引CREATED_DATE也會提高性能很多。

相關問題