2013-11-21 49 views
1

我有一個帶有頁面的網站,每個頁面可能屬於幾個類別。用戶被分配到類別,並且如果頁面被分配了用戶所屬的類別,則他們可以看到該頁面。針對內部查詢的sql優化

最初的每一頁屬於一類,我可以用這個表連接,並檢查權限,像這樣

where Sec.[level] > 0 

現在的網頁可以有多個類別,我試圖改變SP的where語句過濾掉結果,儘管它起作用,但效率非常低。我得到的所有類別的最高權限,如果至少有一個大於零次,則訪問

WHERE 
     (

      (TLA.RecipientTypeID = 2 and (SELECT MAX(CAST(dbo.PersonHasPermission_forSection(CS.SectionID, @pViewersID, 1) AS tinyint)) 
              FROM CONTENT_SECTION CS 
              WHERE CS.ContentID = tla.RecipientID) > 0 
      ) 
      OR 
      (TLA.RecipientTypeID <> 2 AND Sec.[level] > 0) 
     ) 

的或者是因爲只有頁面有多個貓,其他類型的內容仍然只有一個。

我不知道這裏是否有足夠的信息,但任何優化技巧將不勝感激。

+0

該函數('dbo.PersonH​​asPermission_forSection(..)')是問題所在。您需要將其內聯或將其更改爲內聯表值函數。發佈它的內容,我們可以告訴你如何做到這一點。 – RBarryYoung

回答

3

根據你的WHERE語句,慢執行的主要原因是爲內部子查詢中的每一行調用一個函數。我認爲你不應該搜索MAX(),並在這種情況下將它與0進行比較,掃描所有表。相反,它嘗試使用EXISTS像這樣的發現只是一個許可> 0的記錄 - 這是足夠多的:

and EXISTS(SELECT * FROM CONTENT_SECTION CS 
      WHERE CS.ContentID = tla.RecipientID 
      AND 
      (CAST(dbo.PersonHasPermission_forSection(CS.SectionID, @pViewersID, 1) 
         AS tinyint)>0) 
      ) 
+0

Thankyou,這確實提高了效率 – DavidB

+1

@DavidB您將能夠提高速度替換'dbo.PersonH​​asPermission_forSection'調用子查詢返回相同的值。當然,如果它可能和功能邏輯簡單。 – valex

1

的情況下,當你有效率,它往往是真的,重複的函數調用是罪魁禍首。有時,通過消除對該函數的多次調用可以獲得很大的效率增益。一種方法是使用臨時表。所以,這可能是需要探索的。

但是,我想從特定的SQL退一步,因爲我認爲數據建模和方法可能存在潛在的問題。以你所描述的情況爲例:

我有一個帶頁面的網站,每個頁面可能屬於幾個類別。 用戶被分配到類別,並且如果一個頁面被分配了用戶所屬的類別 ,他們可以看到該頁面。

這種情況的最佳數據模型是三個具有多對多關係的「實體」表(類別,用戶和頁面)許多一對多關係意味着兩個附加表的連接(UserCategory和PageCategory):

Example database structure with 5 tables

在這種情況下,讓所有的頁面的列表特定用戶所看到的,你可以只使用一個這樣的查詢樣本(這是相當有效):

SELECT p.* 
FROM UserCategory uc 
    INNER JOIN PageCategory pc ON uc.CategoryID = pc.CategoryID 
    INNER JOIN Page p ON pc.PageID = p.PageID 
WHERE uc.UserID = @pViewersID 

這是一個半笛卡兒連接,但是這是你在這種情況下,想要的東西。還要注意,爲了使用給定的示例查詢獲得最佳SELECT效率,您還需要UserCategory.UserID上的索引。

最後,我刪除了[Level]列,因爲它好像只用於真/假檢查(「大於0」),已經通過UserCategory中的row-exists-or-not來處理。但是,如果您確實需要多個權限級別(不僅僅是0或1),請注意,您還可以在UserCategory中包含一個[Level]列,並在示例查詢中引用它以減少額外成本。

+0

感謝您的詳細解答,不幸的是,它在遊戲中有點晚,以改變任何結構,但感謝您的信息 – DavidB

+0

不客氣......樂於幫助!如果你喜歡,我會很高興看到你有什麼可以做的結構內你有。僅從WHERE子句中推斷出來有點困難。你可以發佈你當前的表結構嗎?務必進行通用化以保護您的業務數據安全。如果你可以發佈你的整個查詢(包括FROM子句)和PersonH​​asPermission_forSection的實現,那也是有幫助的。 –