2013-10-28 68 views
0

我的查詢從15秒變爲0.05秒的時候我在下面的查詢中刪除ORDER BY:MySQL查詢訂單緩慢的,因爲通過與存儲功能

簡化版本:

SELECT field1, fiedl2, field 3, 
    FUNC1(1, 2) AS score1, 
    FUNC2(1, 2) AS score2, 
    FUNC3(1, 2) AS score3, 
    FUNC4(1, 2) AS score4 
FROM table 
WHERE field1 = 1 
ORDER BY (score1 * 1 + score2 * 2 + score3 * 2 + score4 * 4) DESC; 

我有幾個存儲函數可以計算子分數。除了我必須根據總分排序結果。在ORDER BY中,我使用* 2爲子分數增加一些權重以影響總分。

我使用MySQL 5.6.13

有沒有人有一個想法,我怎麼可以使ORDER BY,但不能慢下來? 像是有可能和存儲score#字段和總結它們?

謝謝!

+0

好的,我找到了一些東西。 'score#'是對存儲函數的引用。 ORDER BY是排序方法,它對這些引用進行了大量的比較。所以存儲的函數將被執行很多次。有沒有辦法將存儲函數的返回值設置爲靜態字段? – pascalvgemert

回答

0

您可以在該表中添加total_score列,並定義一個觸發器以便在添加或更新行時自動更新它。然後索引該列,並且ORDER BY total_score應該快。

+0

這是兩個表之間的實時算法。我將一個表的值注入函數中。 – pascalvgemert

+0

在這種情況下,最好考慮將此功能轉換爲與其他表的連接。 –

+0

@RaulLuna這對ORDER BY有什麼幫助? – Barmar

1

時間上的差異是因爲MySql需要創建一個已排序的臨時表並填充數據。由於在使用order by時查詢運行速度較慢,因此問題可能出在存儲臨時數據的磁盤上。您尚未提及您從此查詢返回的行數。您也可以嘗試手動執行MySQL是可能做的步驟,使創建主鍵(order_by_result INT,正INT AUTO_INCREMENT)一個臨時表並插入到它的選擇結果:

Insert into t(order_by_result, n, ...) 
select (score1 * 1 + score2 * 2 + score3 * 2 + score4 * 4),null,... 

和HPW檢查快呢運行 - 如果問題出在您的存儲空間上,您也可以通過這種方式進行檢查。

+0

我正在排序大約2000行,以及返回前20個結果的內容。 – pascalvgemert

+0

所以你說要創建一個臨時表,如:CREATE TEMPORARY TABLE temp_table AS(SELECT field1,.. FROM table)'並對此進行排序? – pascalvgemert

+0

臨時表不是解決方案! :( – pascalvgemert

0

我認爲最好的解決方案是預先計算函數的值並將它們存儲在數據庫中。這樣,即時計算函數值的問題將轉化爲非常簡單的排序查詢。

正如lowleveldesing所說,這種類型的查詢迫使mysql在給出任何輸出之前計算所有寄存器的產品(score1 * 1 + score2 * 2 + score3 * 2 + score4 * 4)

+0

這將是理想的,但不適合這種情況。我需要實時執行算法。 – pascalvgemert