2011-09-24 749 views
9

這是一個奇怪的。我試圖在MySQL中使用視圖(我對MySQL有相當的新意,並且有更多的Sybase和SQL Server的經驗)。任何方式這個新項目我們使用MySQL,因爲它似乎有良好的性能。然而,爲了更簡單地查詢網絡前端,我們決定創建一些視圖,一切運行良好,但它們需要永遠運行。MySQL - 視圖 - 超慢查詢

意見非常簡單,只需選擇語句(這些表確實有幾百萬行)。例如說這個查詢:

SELECT CAST(classifier_results.msgDate as DATE) AS mdate 
     ,classifier_results.objClass AS objClass 
     ,COUNT(classifier_results.objClass) AS obj 
     ,classifier_results.subjClass AS subjClass 
     ,COUNT(classifier_results.subjClass) AS subj 
FROM classifier_results 
WHERE (classifier_results.msgDate >= (curdate() - 20)) 
GROUP BY 
    CAST(classifier_results.msgDate as DATE) 
    ,classifier_results.objClass 
    ,classifier_results.subjClass 
ORDER BY classifier_results.msgDate DESC 

當作爲一個正常選擇運行需要大約1.5秒返回結果。

然而,當這個查詢放入視圖(原樣) - 即

CREATE VIEW V1a_sentiment_AI_current AS  
SELECT CAST(classifier_results.msgDate as DATE) AS mdate 
     ,classifier_results.objClass AS objClass 
     ,COUNT(classifier_results.objClass) AS obj 
     ,classifier_results.subjClass AS subjClass 
     ,COUNT(classifier_results.subjClass) AS subj 
FROM classifier_results 
WHERE (classifier_results.msgDate >= (curdate() - 20)) 
GROUP BY 
    CAST(classifier_results.msgDate as DATE) 
    ,classifier_results.objClass 
    ,classifier_results.subjClass 
ORDER BY classifier_results.msgDate DESC 

查詢需要大約10倍的時間(22-30秒)。所以我想也許有一些優化或查詢緩存,不適用於視圖或可能有一些我們已經錯過了在MySQL配置設置。但是有什麼辦法可以加速這個視圖,所以它只是這個查詢的一個很好的佔位符?

運行EXPLAIN在兩個查詢: 正常的選擇給出了:

1,操作簡便,classifier_results,ALL,idx_date,,,,594845,使用其中;使用臨時;使用文件排序

的視圖中選擇給出:

1,PRIMARY,ALL,,,,,100,
2,衍生classifier_results,ALL,idx_date,,,,594845,使用哪裏;使用臨時;使用文件排序

+0

如果在查看和從視圖中選擇時使用EXPLAIN,你會得到不同的結果嗎? – Cocowalla

+0

已添加到問題中。查詢計劃看起來是一樣的,即時假設eprimary只是從視圖返回,因爲它是嵌套在某種意義上,沒有什麼可以指示20秒+額外運行.... – NightWolf

+1

我認爲'DERIVED'意味着它正在使用一個臨時表,這是殺害性能 – Cocowalla

回答

0

嘗試重新創建一個使用此視圖:關於MySQL的觀點處理算法

CREATE ALGORITHM = MERGE VIEW `V1a_sentiment_AI_current` AS  
SELECT CAST(classifier_results.msgDate as DATE) AS mdate 
    ,classifier_results.objClass AS objClass 
    ,COUNT(classifier_results.objClass) AS obj 
    ,classifier_results.subjClass AS subjClass 
    ,COUNT(classifier_results.subjClass) AS subj 
FROM classifier_results 
WHERE (classifier_results.msgDate >= (curdate() - 20)) 
GROUP BY 
    CAST(classifier_results.msgDate as DATE) 
    ,classifier_results.objClass 
    ,classifier_results.subjClass 
ORDER BY classifier_results.msgDate DESC 

更多信息,可以發現。

+0

好的感謝爲此鏈接。之前的觀點是未定義的。通過嘗試將算法更改爲MERGE給出: 0行受影響,1警告: 1354現在無法在此處使用視圖合併算法(假定未定義的算法)。試圖用TEMPTABLE算法創建視圖很好。所以用UNDEFINED即時猜測它可能使用TempTable作爲未定義似乎在合併和可測試之間做出選擇。所以這可能是問題,因爲手冊說合並更有效率...... – NightWolf

+0

嘗試從視圖中刪除'ORDER BY'子句並查看它是否可以使用MERGE'算法 – Cocowalla

+0

刪除ORDER BY仍然不希望作爲合併工作。 '1354查看合併算法現在不能在這裏使用(假定未定義算法)' – NightWolf

0

由於選擇列表中的count()聚合,MERGE不能用於此處;它可能有助於在這些情況下指定TEMPTABLE來保存引擎不必在它們之間做出決定。一旦我決定使用哪種算法,我會查看EXPLAIN計劃並嘗試添加索引提示或找到缺少的索引。

1

這是一個非常普遍的問題。編寫DRY,可重用的SQL可能非常困難。儘管我找到了一個解決方法。首先,正如其他人已經指出的那樣,您可以並且應該使用VIEW來儘可能地使用set ALGORITHM = MERGE來完成此操作,以便使用它們的任何查詢都在合併SQL語句的where子句上進行了優化,而不是使用VIEW評估可能是災難性大的整個視圖。

在這種情況下,由於組/計數方面的原因您不能使用MERGE,因此您可能需要嘗試使用創建臨時會話表的存儲過程作爲解決方法。

該技術允許您編寫可從中間件/框架代碼訪問並從其他存儲過程內部調用的可重用查詢,因此您可以保持代碼包含,可維護和可重用。

I.e.如果您事先知道查詢將在某些條件下被過濾,請將這些查詢存儲在存儲過程中。 (對數據集進行後過濾可能更有效率,或者組合 - 它取決於您如何使用數據以及需要哪些常用集合)。現在

CREATE PROCEDURE sp_create_tmp_V1a_sentiment_AI_current(parm1, parm2 etc) 
BEGIN 

    drop temporary table if exists tmp_V1a_sentiment_AI_current; 

    create temporary table tmp_V1a_sentiment_AI_current 
    as 
    SELECT CAST(classifier_results.msgDate as DATE) AS mdate 
     ,classifier_results.objClass AS objClass 
     ,COUNT(classifier_results.objClass) AS obj 
     ,classifier_results.subjClass AS subjClass 
     ,COUNT(classifier_results.subjClass) AS subj 
    FROM classifier_results 
    WHERE (classifier_results.msgDate >= (curdate() - 20)) 
    -- and/or other filters on parm1, parm2 passed in 
    GROUP BY 
    CAST(classifier_results.msgDate as DATE) 
    ,classifier_results.objClass 
    ,classifier_results.subjClass 
    ORDER BY classifier_results.msgDate DESC; 

END; 

,你需要這方面的數據進行工作,您隨時調用程序,然後或者選擇的結果(可能有額外的where子句參數),或以任何其他查詢加盟。

該表是一個會話臨時表,因此它會持續超出對該過程的調用。調用代碼可以在完成數據後將其刪除,或者在會話結束或隨後調用存儲區時自動啓動。

希望有幫助。