2011-08-10 62 views
1

我有一個包含group by的SQL視圖。我試圖從使用類似的視圖中選擇。我選擇的列已編入索引,但SQL堅持使用表中的所有行創建臨時表,然後過濾where標準。 (慢)我怎樣才能過濾FIRST?如何使用SQL在使用group by和其他語句時使用的條件

視圖定義

SELECT ListCode, SUM(CASE 
    WHEN ListStatus = 'A' THEN 1 
     ELSE 0 
     END) Active 
FROM ListParticipation 
GROUP BY ListCode 

選擇

SELECT * 
FROM ListParticipationView 
WHERE ListCode like '%ReallyCoolList%' 

順便說一句,如果我用一樣的標準沒有開始通配符SQL計劃並顯示過濾行程在小組彙總之前。

+0

我最好的猜測是,你真正的解決方案是將一個列表傳遞給一個'LIKE'語句,我假設它是一個[多對多關係](http://www.tekstenuitleg.net/en /articles/software/database-design-tutorial/many-to-many.html)。 –

回答

2

您的條件不可SARGable,即它不能使用索引。

使用LIKE%在比較字符串的開頭保證了表掃描。 SQL必須檢查每行中的整個字段以評估匹配。

如果你的ListCode是一個非常長的字符串,也許你應該把它作爲一個int,它是查找表中的PK。然後你可以評估:

WHERE Listcode IN (1, 3, 4, 6)並利用索引。

1

它不是首先過濾,因爲開始通配符阻止索引被使用。基本上,它必須搜索整個字符串 - 所以它仍然必須搜索每一行,因爲charvarchar上的索引通常從第一個字符開始......這大致相當於想知道爲什麼當您的選擇標準僅限於第二列或第三列而非第一列時,多列索引未被使用。

如果你重複ListCode S(如將顯然是這種情況),認爲他們提取到自己的表,然後將新表的id作爲listCodeIdListParticipation表(太替代指標)。如果你有足夠聰明的優化器,它會在他們的表中找到匹配給定野生字符串的所有listCode(應該是唯一的,所以請有一個唯一的約束),然後用它來查詢listCodeId上的fk索引。應該更高性能。

+0

我實際上可以使用索引掃描。我想,我的困惑之處在於,如果我做了:SELECT ListCode,SUM(CASE WHEN ListStatus = 'A',那麼1 ELSE 0 END)主動 FROM ListParticipation WHERE ListCode LIKE '%ReallyCoolList%' GROUP BY ListCode這個表現更好。它正在進行全表掃描,只獲取需要彙總的行,然後進行分組。不知道我需要採取什麼不同的方式才能讓視圖使用相同的計劃。 – John

+0

你沒有收到索引掃描,你正在進行表掃描。我懷疑你的RDBMS不能解決視圖中where語句和分組列之間的關係 - 只要有一個查詢允許它解決這個問題。不過,我不知道他們中有些人能夠解決這個問題。不過,仍然建議將'ListCode's拉出到自己的表中。 –

0

我看到你已經知道爲什麼意見往往是一個壞主意。如果他們打電話給其他觀點,情況會變得更糟如果直接訪問表的SQL語句更快,那就使用它。但是不要使用具有通配符作爲第一個字符的like語句的where子句。這樣做比一個扔掉的查詢anythign其他表明你需要使用一個不同的充技術,如:

  1. 因此大受修復設計
  2. 你需要使用全文索引

如果您在一列中存儲諸如'test,mytest,另一個愚蠢的測試'之類的數據並使用類似子句來查找'mytest'的所有值,那麼您需要規範化表格並正確存儲數據。

如果您的用戶正在搜索條款,他們可能不知道確切的名稱(比如'羅納德里根國家機場'等長期正式的機場名稱,搜索可能是'國家機場'),那麼使用全文索引代替。

如果您沒有特殊原因將%放在前面,那麼請停止操作。