[英]MySQL - Views - Super slow query
這很奇怪。 我正在嘗試在MySQL中使用Views(對於具有Sybase和SQL Server的更多經驗,我是MySQL的新手)。 無論如何,這個新項目我們都在使用MySQL,因為它似乎具有良好的性能。 然而,為了簡化Web前端的查詢,我們決定創建一些視圖,一切都運行良好,但它們需要永遠運行。
視圖非常簡單,只是select語句(這些表中確實有幾百萬行) 。 比如說這個查詢:
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秒)。 所以我想也許有一些優化或查詢緩存不能與Views一起使用,或者我們在MySQL配置中錯過了一些設置。 但有沒有辦法加快這個視圖,所以它只是這個查詢的一個不錯的占位符?
在兩個查詢上運行EXPLAIN:正常選擇給出:
1,SIMPLE,classifier_results,ALL,idx_date ,,,, 594845,使用where; 使用臨時; 使用filesort
視圖選擇給出:
1,PRIMARY ,, ALL ,,,,, 100,
2,DERIVED,classifier_results,ALL,idx_date ,,,, 594845,使用where; 使用臨時; 使用filesort
這是一個非常普遍的問題。 編寫DRY,可重用的SQL可能非常困難。 我找到了一個解決方法。
首先,正如其他人所指出的那樣,你可以而且應該使用VIEWs盡可能使用set ALGORITHM = MERGE來執行此操作,以便使用它們的任何查詢在合並的SQL語句的where子句上進行優化,而不是對整個VIEW進行評估視圖可能是災難性的大。
在這種情況下,由於組/計數方面您無法使用MERGE,因此您可能希望嘗試使用創建臨時會話表的存儲過程作為變通方法。
此技術允許您編寫可從中間件/框架代碼訪問並從其他存儲過程內部調用的可重用查詢,因此您可以保持代碼包含,可維護和可重用。
即如果您事先知道將在某些條件下過濾查詢,請將它們放在存儲過程中。 (對數據集進行后置過濾或組合可能更有效 - 這取決於您如何使用數據以及需要哪些常用集合)。
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子句參數)或者在任何其他查詢中加入它。
該表是會話臨時表,因此它將持續超出對過程的調用。 調用代碼可以在數據完成后丟棄它,也可以在會話進行或后續調用sproc時自動進行。
希望這很有幫助。
嘗試使用以下方法重新創建視圖:
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
有關MySQL視圖處理算法的更多信息,請參見此處 。
由於select列表中的count()聚合,因此無法在此處使用MERGE; 在這些情況下,它可能有助於指定TEMPTABLE以保存引擎不必在它們之間做出決定。 一旦我決定使用哪種算法,我會查看EXPLAIN計划並嘗試添加索引提示或找到缺少的索引。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.