2017-06-14 61 views
0

我有一張表(可以稱之爲「操作」),列出了由一堆不同客戶端完成的所有操作。尋找一種快速方法從大型數據庫表中獲取不同值的列表

我想獲取特定客戶端的不同操作類型的列表。 我也知道,有系統

我嘗試了明顯的100種動作類型:

SELECT DISTINCT actionType FROM actions WHERE clientId = @clientId 

但它是非常緩慢的,由於大量的表中的記錄。

我現在正在使用的查詢存在獲得actionTypes的名單,我懷疑會更快:

SELECT 'actionType1' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
    clientId = @clientID AND actionType = 'actionType1') 
UNION 
SELECT 'actionType2' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
    clientId = @clientID AND actionType = 'actionType2') 
UNION 
. 
. 
. 
UNION 
SELECT 'actionType100' WHERE EXISTS (SELECT TOP 1 * FROM actions WHERE 
     clientId = @clientID AND actionType = 'actionType100') 

雖然我希望這是更快(希望足夠快的)感覺對我來說非常hacky 有人可以建議一個更好的方法來做到這一點?

乾杯, 一個

更新: 的SELECT DISTINCT正在採取昨日下午3秒,其現在立即運行!我想知道是否有人添加了索引。我會檢查

由於幾個人懷疑,第二個查詢實際上比明顯慢得多,它需要4秒鐘跑!

+2

其實我認爲這會慢得多,因爲現在你做100個查詢。 –

+2

你是否有'clientId'上的索引涵蓋'actionType'? – iamdave

+0

沒有集羣,可能需要測試 – AidanO

回答

1

幾個設計說明在這裏。如果我理解正確,動作表中的動作是持續存在的。 1)如果你有一組預定義的動作類型,我的第一個建議是刪除字符串,並用整數替換它們作爲動作類型標識符,這將是一個查找整數值到動作類型的實際名稱在一個單獨的動作類型表中。然後,在動作類型標識中創建一個外鍵和一個非聚集索引(如果您主要對這些索引感興趣,可以使用非空動作類型對索引進行過濾)。這樣,在使用操作類型進行篩選時,您可以降低記錄大小,聚集索引大小和整體性能。 2)如果你不能改變數據庫設計,或者查詢表的操作類型太廣泛,你應該在client_id中創建一個非聚集索引,其action_type作爲包含列(這也可以被過濾爲非null動作類型值來縮小索引)。

+0

謝謝,非聚集索引已經在這裏完成了。 – AidanO

-1

如果您在actionType上創建了一個羣集索引,它應該會大大提高性能。

1

SELECT actionType FROM actions WHERE clientId = @clientId需要運行多長時間?我認爲它是主要的瓶頸,而不是DISTINCT操作

看看查詢計劃是否確定,但是如果clientID未被索引,那麼它可能是全表掃描來提取所需的數據。

一天結束時,數據庫引擎將做一個散列表來獲得一個獨特的(就像你SELECT x FROM y GROUP BY x),這是一個需要訪問所有數據的快速操作。 YOu不會以任何方式使它快速分解;速度的99%將下降到拉入數據所需的時間;作爲行閱讀器遍歷表添加元素到一個散列表是微不足道的

+0

選擇actionTypes大約需要7秒!選擇不同的動作類型所需的時間不到一秒鐘...... – AidanO

+1

如果您正在重複運行查詢(因爲它被緩存),所以始終難以真正進行性能測試。索引列和包含操作類型的建議是合理的;這意味着索引可以滿足所有查詢而不從表中檢索行。使其更快的唯一方法是使用觸發器來維護一個單獨的查找表,只有在插入 –

+0

時,纔會有不同的值,這個查詢表不錯,但如果還有其他更多的時間緊迫的問題,可能是可用的。 – AidanO

相關問題