2017-04-11 101 views
1

我們有一個下面的查詢需要大約6-8秒執行。 記錄總數:522954需要優化SQL查詢 - 花費大量的時間來執行

(SELECT 
     * 
     FROM 
     tbl_insights_copy 
     WHERE insightscat = 21 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC 
     LIMIT 5) 
     UNION 
     (SELECT 
     * 
     FROM 
     tbl_insights_copy 
     WHERE insightscat = 22 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC 
     LIMIT 5) 
     UNION 
     (SELECT 
     * 
     FROM 
     tbl_insights_copy 
     WHERE insightscat = 23 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC 
     LIMIT 5) 
     UNION 
     (SELECT 
     * 
     FROM 
     tbl_insights_copy 
     WHERE insightscat = 24 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC 
     LIMIT 5) 

別人的幫助來優化這個查詢,以減少執行時間。 在此先感謝。

+2

顯示您的tbl_insights_copy表模式 – scaisEdge

回答

1

你是一個變化之間唯一選擇,另外,是列insightscat的過濾器值,我不知道這是你想要的,但....

您可以嘗試爲IN指令這個。例如:

SELECT 
     * 
FROM 
     tbl_insights_copy 
     WHERE insightscat in (20,21,22,23,24) 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC 
+2

又在哪裏是'LIMIT 5'每個''insightscat你 – TriV

+0

可以,只要你想在句末加上限制語句:SELECT * 從 tbl_insights_copy WHERE insightscat在( 20,21,22,23,24) AND submitedon> = UNIX_TIMESTAMP(DATE_SUB(NOW(),INTERVAL 30 DAY)) ORDER BY submitedon DESC LIMIT 5 – Developer90

+0

如果你想從each_中得到5 _,這將不起作用。 –

0

對於此查詢:

SELECT ic.* 
FROM tbl_insights_copy ic 
WHERE insightscat = 21 AND 
     submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
ORDER BY submitedon DESC 
LIMIT 5 

你想在tbl_insights_copy(insightscat, submittedon)的索引。

這應該適用於所有的子查詢。這可能是MySQL的最佳方法。

0
SELECT t1.* 
    FROM (SELECT t.* ,ROW_NUMBER() OVER (ORDER BY insightscat) AS Row 
     FROM 
     (select * from   
     tbl_insights_copy 
     WHERE insightscat in (20,21,22,23,24) 
     AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
     ORDER BY submitedon DESC) as t) t1 
    WHERE Row <= 5 
+0

「OVER」語法在MySQL中尚不可用。它在MariaDB 10.2中可用。 –

0

沒有SHOW CREATE TABLE,我將不得不猜測,你沒有最佳

INDEX(insightscat, submitedon) 

由於SELECTs是不同的,使用UNION ALL而不是默認的UNION DISTINCT的。這將避免在20行上進行不必要的(但快速)重複傳送。

如果你想20行

如果是這樣,我的上述建議可能是最好的。

如果你想6行

如果只想從那些insightscats的任何最新5,則有3種可能性。

A計劃

Developer90說,在他的評論是什麼。

B計劃

(SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5) 
UNION ALL 
(SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5) 
UNION ALL 
(SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5) 
UNION ALL 
(SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5) 
ORDER BY ORDER BY submitedon DESC LIMIT 5; 

每個SELECT非常快與我的索引。然後,UNION的20行再次排序,並應用LIMIT 5。再次,非常快。

使用開發者90建議的IN可能會或可能不會有效地使用我的索引。你使用什麼版本?

C計劃

此選項擊中或錯過。也就是說,它的性能在很大程度上取決於數據分佈是非常快還是非常緩慢:Developer90 + INDEX(submitedon)(不包括insightscat)。