2015-04-22 62 views
0

我正在尋找如何通過更改(例如)如何優化(如果可能)用於閱讀風信息的SQL查詢的性能的幫助(請參見下文)。數據庫結構,查詢或其他東西?如何提高風數據SQL查詢性能

我使用託管數據庫來存儲具有超過800,000行風況信息(速度和方向)的表格。從風速計每分鐘添加一次新數據。使用PHP腳本訪問數據庫,該腳本創建一個網頁,用於使用Google的可視化API繪製數據。

該網頁大約需要15秒才能加載。我已在PHPJavascript部分中添加了一些時間度量,以分析代碼並找出可能需要改進的地方。

我希望改進的一個部分是下面的查詢,它大約需要4秒的時間來執行。查詢的目的是將15分鐘的風速(最小/最大/平均值)分組,並計算測量期間的平均值和總的最小/最大值。

SELECT AVG(d_mean) AS group_mean, 
     MAX(d_max) as group_max, 
     MIN(d_min) AS 
     group_min, 
     dir, 
     FROM_UNIXTIME(MAX(dt),'%Y-%m-%d %H:%i') AS group_dt 
FROM (
    SELECT @i:[email protected]+1, 
      FLOOR(@i/15) AS group_id, 
      CAST(mean AS DECIMAL(3,1)) AS d_mean, 
      CAST(min AS DECIMAL(3,1)) AS d_min, 
      CAST(max AS DECIMAL(3,1)) AS d_max, 
      dir, 
      UNIX_TIMESTAMP(STR_TO_DATE(dt, '%Y-%m-%d %H:%i')) AS dt 
      FROM table, (SELECT @i:=-1) VAR_INIT 
      ORDER BY id DESC 
) AS T 
GROUP BY group_id 
LIMIT 0, 360 

... 

$oResult = mysql_query($sSQL); 

該表具有以下結構:

1 ID  int(11)  AUTO_INCREMENT 
2 mean varchar(5) utf8_general_ci 
3 max  varchar(5) utf8_general_ci 
4 min  varchar(5) utf8_general_ci 
5 dt  varchar(20) utf8_general_ci // Date and time 
6 dir  varchar(5) utf8_general_ci 

以下設置用於:

  • 數據庫:MariaDB的,42年5月5日-MariaDB的-1〜喘息
  • 數據庫客戶端版本:libmysql - 5.1.66
  • PHP版本:5.6
  • PHP的擴展:mysqli
+1

'5 DT VARCHAR(20)utf8_general_ci //日期和time'不要儲存日期+時間在一個字符字段。使用日期時間或時間戳(如果可用)並且類似於速度和方向:使用整數,數字或甚至浮點類型,但不使用**字符類型來存儲它們。 – wildplasser

+1

你可以發佈解釋和數據模型嗎?另外:請格式化你的代碼,使其變得更可讀。 –

+0

您的問題的很大一部分可能是隱式轉換。這也會讓您在查詢時出現不必要的錯誤風險。只有80萬行可能不是什麼大問題,但仍然是一個問題。和糟糕的設計。 –

回答

1

我非常同意目前的意見 - 清理數據,因爲你把它放到表中。

一旦你做清潔,讓我們避免子查詢做...

SELECT MIN(dt) as 'Start of 15 mins', 
     FORMAT(AVG(mean), 1) as 'Avg wind speed', 
     ... 
    FROM table 
    GROUP BY FLOOR(UNIX_TIMESTAMP(dt)/900) 
    ORDER BY FLOOR(UNIX_TIMESTAMP(dt)/900); 

我不明白LIMIT的目的。我猜你一天想要幾天。爲此,我建議您在FROMGROUP BY之間添加(之後清潔)。

WHERE dt >= '2015-04-10' 
     AND dt < '2015-04-10' + INTERVAL 7 DAY 

這將顯示7天,從'2015-04-10'上午開始。

爲了處理的800K一個表,你會決然需要(再次,清洗):

INDEX(dt) 

來清潔800K行,有多種方法。我建議創建一個新表,複製數據,測試並最終交換。類似...

CREATE TABLE new (
    dt DATETIME, 
    mean FLOAT, 
    ... 
    PRIMARY KEY(dt) -- assuming you have only one row per minute? 
) ENGINE=InnoDB; 

INSERT INTO new (dt, mean, ...) 
    SELECT str_to_date(...), 
      mean, -- I suspect that the CAST is not needed 
      ...; 

編寫新的選擇並測試它。

現在new缺少較新的行。您可以重建它,並希望在一分鐘內完成所有事情,或者玩其他遊戲。讓我們知道你是否需要幫助。

+0

對於不清楚細節,我感到抱歉。你對使用LIMIT的假設是正確的。 – Watts

+0

我製作了一份表格的副本,然後我遵循了您的建議,並更改了表格中的兩種數據類型,並重寫了SQL查詢。一切正常。至於性能,查詢執行速度大約爲1秒左右,所以它的大約是。快25%。 – Watts

+0

我錯過了INDEX(dt)部分。你能否解釋一下這個目的是什麼?這是一次性的任務,通過運行查詢,如「CREATE INDEX index_name ON table_name(column_name);」?索引是我應該使用的東西,還是數據庫的內部問題? – Watts