2009-09-09 78 views
6

ATM我想了解如何有效地使用數據庫inidices,並希望得到一些專家意見。目前我沒有任何性能問題。我只是想知道,你會如何處理您的索引與此查詢:如何加快此查詢?

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM A    
    INNER JOIN B ON A.event=B.event 
    INNER JOIN C ON B.state=C.id 
    LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.id IN(12,13,14,15,...) 
    ORDER BY B.event, B.timestamp 

A.idC.idD.id已經是主鍵

UPDATE 通常我會把INDEX(A.event )和INDEX(B.event,B.timestamp)。它是否正確? B.event,B.state和B.hur呢?

+0

正確,但檢查是否實際使用B.timestamp。 – Pomyk 2009-09-09 09:31:04

+0

每個表格有多大,以及您希望從給定查詢中匹配多少行。你正在使用哪個數據庫? – 2009-09-09 10:19:39

+0

另外,數據添加到表中的頻率以及您希望運行查詢的頻率如何? – 2009-09-09 10:23:04

回答

3

重寫查詢,因爲這:

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM B    
INNER JOIN 
     C 
ON  C.id = B.state 
LEFT OUTER JOIN 
     D 
ON  D.id = B.hur 
WHERE B.event IN 
     (
     SELECT event 
     FROM A 
     WHERE A.id IN (12, 13, 14, 15) 
     ) 
ORDER BY 
     B.event, B.timestamp 

,並創建B (event, timestamp)

2

您可以將索引添加到WHERE和ORDER BY子句中的所有內容中。 Ie A.event,B.event和B.timestamp。

+1

請勿盲目添加索引。見Lieven的答案。盲目添加索引可能會損害性能,因爲每個索引都需要維護。在某些情況下,如小型表格,這將會傷害到IO所使用的維護可能在其他地方使用。有時,對小表進行全表掃描比索引要好。 – jim 2009-09-09 12:28:58

+0

我很想刪除我的答案;然而,吉姆的評論是有用的信息,所以應該留下答案? – darasd 2009-09-09 14:09:17

0
SELECT B.event, B.system, COALESCE(C.surname) || ' ' || COALESCE(C.forename) AS name, C.label, B.timestamp 
FROM A    
INNER JOIN B ON A.event=B.event 
INNER JOIN C ON B.state=C.id 
LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.event = ANY(:visits) 
ORDER BY B.event, B.timestamp 

此外,ORDER BY會嚴重降低速度。 確保這些索引:

A.event 
B.event 
B.state 
C.id 
B.timestamp 
3

我平時努力加快我的查詢

  1. 分析執行計劃的時候採取這些步驟。
  2. 嘗試創建(覆蓋)索引以消除表掃描。
  3. 嘗試創建(覆蓋)索引以消除索引掃描。

至於你詢問,你不會出差錯創建索引上

  • A.event
  • B.event
  • B.state
  • B.Hur
+0

爲B.event和B.state創建獨立索引與在(B.event,B.state)上創建索引不同。區分這一點很重要,因爲它對性能有直接影響。 – MatBailie 2009-09-09 10:18:02

+0

@Dems:如果在我的回答中沒有說明問題,那你說的是對的。 – 2009-09-09 11:12:13

1

我會添加索引到任何加入,在where子句或按順序by子句。

在這種情況下添加以下的索引(假設ID字段是主鍵和索引已經):

  1. A.event
  2. B.event
  3. B.state
  4. B.許
  5. B.event,B.timestamp(這兩個字段的組合索引)

第五個,作爲一個指數組合應該加快排序。

您需要調整索引的數量,防止將記錄插入表中時出現的任何性能下降(添加到表中的索引越多,插入和更新就越慢,因爲索引需要更新) 。

2

一個綜合指數要注意的是,在索引中字段的順序是非常重要的是很重要的。

的指標是,從某種意義上說,搜索樹。如果您索引(B.event,B.state),那麼樹會將所有記錄與保存「事件」字段組合在一起,然後通過「狀態」字段對其進行排序。

如果然後來查詢索引「b.state = X」,該指數將是沒有多大用處的;該索引首先由「事件」排序。


在您的例子:
- 通過它過濾器A的 「事件」 字段
- 加入A.event到B.event
- 加入B.state到C.id
- 加入B.hur = D.id
- 由B.event訂購,B.timestamp

重要的是要注意,優化將查看您的表和索引的統計信息,然後可能重新排列順序連接。結果將是相同的,但順序可能會給出不同的性能,而優化者的工作是嘗試找到最佳性能。

在你的情況我希望B.event的才能是極爲重要的。簡單地說,因爲這是結果輸出的順序,AND就是你過濾的字段。

接下來你加入B.state到C.id.因此在C.id上擁有和索引是很好的,它使聯接更快。但同樣,將B表數據按順序排列好也可以使連接更快。

但是,具有上B.event的索引,並且上B.state一個單獨的索引可以產生小。 B.state索引變得毫無意義,因爲我們使用了B.event索引。如果將兩者合併爲一個索引(b.event然後是b.state),執行計劃可能會找到一種方法來使用索引的b.state部分。

最後,如果將所有字段放在索引中,索引確實會變大,但查詢可能永遠不需要查看錶格。信息在索引中。從索引到表格以找到「缺失」字段所用的時間與連接的時間相似。因此,爲了讀取性能,向索引添加額外的字段可能是非常有效的。

我威特靈現在,但總結是這樣的:
- 通常情況下,在不同的領域不同的指數不扎堆
使用 - 對於複合索引,你指定的字段的順序有差別
- 向索引添加'額外'字段使其更大,但也可以使查詢更快
- 執行計劃的順序比查詢的順序更重要
- 但是您擁有的索引可以確定順序執行計劃

這種工作有沒有絕對的答案。它非常依賴於你的數據,它更接近於藝術。

一種選擇是過載使用索引表,看看產生的執行計劃,並刪除那些不必要的索引。

但即使有一個警告適用。因爲執行計劃是依賴於數據(和表格統計)的,所以在表格中有真實世界的數據是非常重要的。雖然表格有10或100行,但一個執行計劃可能是最快的。但是當你得到數百萬行時,執行計劃可能會改變,並從不同的索引中受益。

2

運行講解分析查詢,閱讀它 - 如果它不能幫助 - 把解釋分析輸出上explain.depesz.com,並檢查它「說」。