2014-01-29 108 views
1

我有JPA生成的SQL,最壞的情況下有1250行。將SQL降低了40%,但運行速度降低了60倍?

我的查詢結構是嵌套在查詢的WHERE語句內的20個子查詢。該查詢在0.015秒內運行。

我試圖優化我的查詢,因爲我注意到我在子查詢中重用了很多連接(例如,兩個子查詢只有WHERE語句不同)。這將SQL降低到750行和12個子查詢,但由於某些原因,運行需要0.9秒。

有什麼解釋嗎?當有更多的數據可用時,我可能試圖使查詢以更快的速度運行得更快?

感謝

+0

你有沒有在田裏指標包括在where子句中? – opalenzuela

+0

這是非常神奇的。如何提供你的SQL代碼,表結構和查詢計劃? – Sergio

回答

0

由於問題中提供的信息有限,我只能推測在特定情況下執行時間增加的原因,但其中的長短之處在於較少的代碼不等於較快的查詢。

「簡化」查詢的主要原因之一可能會導致更長的執行時間,因爲簡化意味着不再使用索引,因爲儘管查詢看起來更加簡單,但實際上要求優化器做更多的事情複雜。

想象一下這個簡單的模式:

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.AT2.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 

Example on SQL Fiddle

0

也許這些多餘的線條創建更小的表(或選擇更少的數據)那麼你有ATM機的,因此你可以比較表(數據)更迅速。但是現在,由於您減少了較小的表的數量並可能增加了較大的表的數量,因此當您運行特定查詢時,查詢必須翻閱更大的表(更多數據),因此它們需要更多時間。

更多的數據來比較=更多的處理時間

+0

是的,謝謝這是問題。事實證明,儘管有些子查詢共享了一些連接,但我合併它們的方式涉及到加入新的表,以便新的子查詢可以包含所需的所有連接。這意味着新查詢中的每個WHERE語句都必須遍歷一個比以前更大的表。 – user2819101

0

如果查詢跑那麼快,那麼它不處理很多行。

很可能,連接正在使用索引進行處理。引擎可以將索引加載到內存中並處理查詢 - 甚至可能永遠不會觸及原始數據。

當你兌現了加入無where條款,一些事情發生了:

  1. 你知道有讀取和寫入數據的額外開銷;
  2. 正在處理的數據量可能大於任何子查詢中的數據量;
  3. 其他優化 - 可能會消除大部分處理 - 不會發生。