2015-05-26 33 views
1

我想問一個具體的視圖和潛在的優化。聯合/交叉連接視圖的優化

似乎很偶然的表設置 - 客戶(約50.000行)和用戶(約250行),而大多數用戶可以訪問所有客戶(事實上,在客戶的地理位置有不同的權限級別,但它似乎沒有關係到這個問題,我會在下面發佈其他問題),有些用戶(RoleId = 1)只能訪問他們自己的客戶。 我以前的coleague提出了一個數據庫視圖來評估某個用戶是否可以訪問某個客戶。

下面是一個視圖定義。

CREATE VIEW [dbo].[ViewUserAllowedCustomer] 
AS 
SELECT 
     u.[Id] UserId 
    , c.[Id] CustomerId 
FROM [dbo].[User] u 
    CROSS JOIN [dbo].[Customer] c 
WHERE 
    u.[RoleId] NOT IN (1) --Specific role for which the below part is required 

UNION 

SELECT 
     u.[Id] UserId 
    , c.[Id] CustomerId 
FROM [dbo].[User] u 
    JOIN [dbo].[Customer] c ON u.[EmployeeId] = c.[EmployeeId] 

現在我正在尋找一種更好的方式來定義這一觀點,並可能刪除union join or cross join或者它甚至傷害的表現?
我想知道是否有任何最佳做法或完全不同的方法比這裏使用的。至少我要在這裏添加UNION ALL而不是UNION

和附加的問題 - 一個想法來到我的腦海:(當客戶有 總是一個地點:否表用戶m)

  • 要對客戶的 地理位置另一個許可延長這一觀點。
  • 目前我在少數父視圖中檢查它額外 - 它會 無論如何顯着提高父視圖的性能?

在此先感謝

編輯: 根據戈登的回答,我想如下修改視圖,它幫助了很多。

現在我正在考慮更多地考慮這種觀點的用法 - 我的意思是,在這種情況下(大多數用戶可以訪問客戶)是更好的方法,只顯示受限制的客戶並詢問客戶並且用戶不在所選視圖中? (應用程序是用SP 2010以上的C#.NET MVC編寫的)。

SELECT u.[Id] as UserId, c.[Id] as CustomerId 
FROM [dbo].[User] u JOIN 
    [dbo].[Customer] c 
    ON u.[EmployeeId] = c.[EmployeeId] 
UNION ALL 
SELECT u.[Id] as UserId, c.[Id] as CustomerId 
FROM [dbo].[User] u CROSS JOIN 
    [dbo].[Customer] c 
WHERE NOT EXISTS (SELECT 1 FROM dbo.[User] u2 WHERE u2.Id = u.Id AND u.RoleId = 1) --this here might be changed for a casual != rule on RoleId, but this describes the original idea, which I think is pretty good 

回答

1

試圖獲得與查詢更好的性能:

CREATE VIEW [dbo].[ViewUserAllowedCustomer] 
AS 
SELECT 
     u.[Id] UserId 
    , c.[Id] CustomerId 
FROM [dbo].[User] u 
    CROSS JOIN [dbo].[Customer] c 
WHERE 
    u.[RoleId] != 1 --Specific role for which the below part is required 

UNION ALL 

SELECT 
     u.[Id] UserId 
    , c.[Id] CustomerId 
FROM [dbo].[User] u 
    JOIN [dbo].[Customer] c ON u.[EmployeeId] = c.[EmployeeId] 
WHERE u.[RoleId] = 1 

新理念(除去uniun)
它接縫你想有一個可以與訪問用戶的白名單用戶。
如果是這樣,我會建議有一個用戶無法訪問的黑名單。
像這樣的東西可能會有所幫助:

CREATE VIEW [dbo].[ViewUserNotAllowedCustomer] 
AS 
SELECT 
     u.[Id] UserId 
    , c.[Id] CustomerId 
FROM [dbo].[User] u 
    CROSS JOIN [dbo].[Customer] c 
WHERE 
    u.[RoleId] = 1 AND u.[EmployeeId] != c.[EmployeeId] 
+0

謝謝,這正是我幾秒前編輯時所想的! – Zax

+0

歡迎您朋友。 –

1

什麼在此查詢會降低性能不是cross join,但union。它有刪除重複的附加邏輯。

嘗試措辭這個有點不同:

SELECT u.[Id] as UserId, c.[Id] as CustomerId 
FROM [dbo].[User] u JOIN 
    [dbo].[Customer] c 
    ON u.[EmployeeId] = c.[EmployeeId] 
UNION ALL 
SELECT u.ID as UserId, c.ID as CustomerId 
FROM [dbo].[User] u JOIN 
    [dbo].[Customer] c 
    ON u.[EmployeeId] = c.[EmployeeId] 
WHERE NOT EXISTS (SELECT 1 FROM dbo.[User] u2 WHERE u2.EmployeeId = u.EmployeeId AND u.RoleId = 1); 

你想在User(EmployeeId, RoleId)的索引。

+0

我的想法,但我想有一個選擇一個錯字。我已經在編輯這個問題時做了它,現在它的工作更順利。謝謝。 – Zax

+0

@Zax。 。 。子查詢中的表別名應該是'u2'(就像現在這樣)。 –