2012-08-15 186 views
0

我正在嘗試提高應用程序的性能。我可能需要創建在cron上運行的彙總表,所以應用程序不需要花費太多時間(5-10秒)。這是最好的主意嗎?加快mysql查詢的速度

如下表:

mysql> describe school_data_sets_numeric_data; 
+--------------+---------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+--------------+---------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
| data_set_nid | int(11)  | NO | MUL | NULL |    | 
| school_nid | int(11)  | NO | MUL | NULL |    | 
| year   | int(11)  | NO | MUL | NULL |    | 
| description | varchar(255) | NO |  | NULL |    | 
| value  | decimal(18,5) | NO |  | NULL |    | 
+--------------+---------------+------+-----+---------+----------------+ 
6 rows in set (0.00 sec) 

而下面的查詢(每個data_set_nid一所學校的運行一次)

這個查詢運行速度快(0秒):

SELECT year, description, CONCAT(FORMAT((value/(SELECT SUM(value) 
FROM `school_data_sets_numeric_data` as numeric_data_inner 
WHERE year = numeric_data_outer.year and data_set_nid = numeric_data_outer.data_set_nid and school_nid = numeric_data_outer.school_nid)) * 100, 2), '%') as value 
FROM `school_data_sets_numeric_data` as numeric_data_outer 
WHERE data_set_nid = 38251 and school_nid = 32805 ORDER BY id DESC; 

說明:

+----+--------------------+--------------------+------+---------------------------------------------+--------------+---------+-----------------------------------------------------------------------------------------------------------+------+-----------------------------+ 
| id | select_type  | table    | type | possible_keys        | key   | key_len | ref                          | rows | Extra      | 
+----+--------------------+--------------------+------+---------------------------------------------+--------------+---------+-----------------------------------------------------------------------------------------------------------+------+-----------------------------+ 
| 1 | PRIMARY   | numeric_data_outer | ref | data_set_nid,data_set_nid_2,school_nid  | data_set_nid | 8  | const,const                        | 17 | Using where; Using filesort | 
| 2 | DEPENDENT SUBQUERY | numeric_data_inner | ref | year,data_set_nid,data_set_nid_2,school_nid | data_set_nid | 8  | rocdocs_main_drupal_7.numeric_data_outer.data_set_nid,rocdocs_main_drupal_7.numeric_data_outer.school_nid | 9 | Using where     | 
+----+--------------------+--------------------+------+---------------------------------------------+--------------+---------+-----------------------------------------------------------------------------------------------------------+------+-----------------------------+ 

這個查詢運行速度慢(1.43秒):

SELECT year, description, CONCAT(FORMAT((SUM(value)/(SELECT SUM(value) 
FROM `school_data_sets_numeric_data` as numeric_data_inner 
WHERE year = numeric_data_outer.year and data_set_nid = numeric_data_outer.data_set_nid)) * 100, 2), '%') as value 
FROM `school_data_sets_numeric_data` as numeric_data_outer 
WHERE data_set_nid = 38251 GROUP BY year,description ORDER BY id DESC; 

解釋:

+----+--------------------+--------------------+------+----------------------------------+----------------+---------+-------+-------+----------------------------------------------+ 
| id | select_type  | table    | type | possible_keys     | key   | key_len | ref | rows | Extra          | 
+----+--------------------+--------------------+------+----------------------------------+----------------+---------+-------+-------+----------------------------------------------+ 
| 1 | PRIMARY   | numeric_data_outer | ref | data_set_nid,data_set_nid_2  | data_set_nid_2 | 4  | const | 90640 | Using where; Using temporary; Using filesort | 
| 2 | DEPENDENT SUBQUERY | numeric_data_inner | ref | year,data_set_nid,data_set_nid_2 | year   | 4  | func | 38871 | Using where         | 
+----+--------------------+--------------------+------+----------------------------------+----------------+---------+-------+-------+----------------------------------------------+ 
+0

你的表中有多少個不同的'school_nid'? – arnoudhgz 2012-08-15 12:32:52

+0

有5446個不同的school_nids – 2012-08-15 12:38:34

回答

-1

相關子查詢/子選擇往往是一個bottelneck - 部分原因是由於一個事實,即MySQL只擁有一個嵌套循環連接算法並沒有散列連接/合併連接。

我會嘗試加入你的主選擇到一個派生表,其中包含你需要的所有SUM值。

-1

你試過對那個查詢解釋嗎?它會解釋它使用了什麼,並沒有幫你選擇正確的索引,但是,「data_set_nid = numeric_data_outer.data_set_nid))* 100,2),'%')」可能是所有的最慢部分..

示例:

查找上週的所有數據。

select * from mything where adddate(day, +7, mydate)>now 

因爲計算是在球場上,這將是緩慢

其中

select * from mything where mydate>adddate(day,-7,now) 

將是快的,因爲它是一個常數。