我有JPA
生成的SQL,最壞的情況下有1250行。將SQL降低了40%,但運行速度降低了60倍?
我的查詢結構是嵌套在查詢的WHERE
語句內的20個子查詢。該查詢在0.015秒內運行。
我試圖優化我的查詢,因爲我注意到我在子查詢中重用了很多連接(例如,兩個子查詢只有WHERE
語句不同)。這將SQL降低到750行和12個子查詢,但由於某些原因,運行需要0.9秒。
有什麼解釋嗎?當有更多的數據可用時,我可能試圖使查詢以更快的速度運行得更快?
感謝
我有JPA
生成的SQL,最壞的情況下有1250行。將SQL降低了40%,但運行速度降低了60倍?
我的查詢結構是嵌套在查詢的WHERE
語句內的20個子查詢。該查詢在0.015秒內運行。
我試圖優化我的查詢,因爲我注意到我在子查詢中重用了很多連接(例如,兩個子查詢只有WHERE
語句不同)。這將SQL降低到750行和12個子查詢,但由於某些原因,運行需要0.9秒。
有什麼解釋嗎?當有更多的數據可用時,我可能試圖使查詢以更快的速度運行得更快?
感謝
由於問題中提供的信息有限,我只能推測在特定情況下執行時間增加的原因,但其中的長短之處在於較少的代碼不等於較快的查詢。
「簡化」查詢的主要原因之一可能會導致更長的執行時間,因爲簡化意味着不再使用索引,因爲儘管查詢看起來更加簡單,但實際上要求優化器做更多的事情複雜。
想象一下這個簡單的模式:
CREATE TABLE T1 (ID INT AUTO_INCREMENT PRIMARY KEY, A INT);
CREATE TABLE T2 (ID INT AUTO_INCREMENT PRIMARY KEY, A INT, B INT);
CREATE INDEX IX_T2_A ON T2 (A);
CREATE INDEX IX_T2_B ON T2 (B);
現在,假設我有以下查詢:
SELECT COUNT(T1.ID)
FROM T1
INNER JOIN
( SELECT ID
FROM T2
WHERE A IN (1, 10)
UNION
SELECT ID
FROM T2
WHERE B IN (1, 10)
) T2
ON t2.ID = t1.ID;
你可能會認爲,這可能是「簡化」刪除UNION
如下:
SELECT COUNT(T1.ID)
FROM T1
INNER JOIN
( SELECT ID
FROM T2
WHERE A IN (1, 10)
OR B IN (1, 10)
) T2
ON t2.ID = t1.ID;
但是,通過結合您的標準,您確保不會使用索引(在T2.A
或T2.B
),因爲優化程序正試圖同時執行這兩個操作。因此,不是使用兩個索引,而是執行全表掃描,根據數據分佈情況,這可能成本更高。
這種運行EXPLAIN
時證實:
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS FILTERED EXTRA
1 PRIMARY <derived2> system (null) (null) (null) (null) 1 100
1 PRIMARY T1 const PRIMARY PRIMARY 4 const 1 100 Using index
2 DERIVED T2 index IX_T2_A IX_T2_A 5 (null) 1 100 Using where; Using index
3 UNION T2 index IX_T2_B IX_T2_B 5 (null) 1 100 Using where; Using index
(null) UNION RESULT <union2,3> ALL (null) (null) (null) (null) (null) (null)
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS FILTERED EXTRA
1 PRIMARY <derived2> system (null) (null) (null) (null) 1 100
1 PRIMARY T1 const PRIMARY PRIMARY 4 const 1 100 Using index
2 DERIVED T2 ALL IX_T2_A,IX_T2_B (null) (null) (null) 1 100 Using where
也許這些多餘的線條創建更小的表(或選擇更少的數據)那麼你有ATM機的,因此你可以比較表(數據)更迅速。但是現在,由於您減少了較小的表的數量並可能增加了較大的表的數量,因此當您運行特定查詢時,查詢必須翻閱更大的表(更多數據),因此它們需要更多時間。
更多的數據來比較=更多的處理時間
是的,謝謝這是問題。事實證明,儘管有些子查詢共享了一些連接,但我合併它們的方式涉及到加入新的表,以便新的子查詢可以包含所需的所有連接。這意味着新查詢中的每個WHERE語句都必須遍歷一個比以前更大的表。 – user2819101
如果查詢跑那麼快,那麼它不處理很多行。
很可能,連接正在使用索引進行處理。引擎可以將索引加載到內存中並處理查詢 - 甚至可能永遠不會觸及原始數據。
當你兌現了加入無where
條款,一些事情發生了:
你有沒有在田裏指標包括在where子句中? – opalenzuela
這是非常神奇的。如何提供你的SQL代碼,表結構和查詢計劃? – Sergio