2009-09-30 44 views
1

我可以通過任何方式優化以下查詢:Linq2SQL:優化查詢?

目標是嘗試找到類型4的客戶,該類型4也基於其增值稅和電子郵件而存在爲類型2。客戶端可以有一個或多個客戶端用戶。

(我都合適的指標設置,我保證)

from e in Clients.Where(h => h.ClientTypeId==4) 
join u in ClientUsers on e.Id equals u.ClientId 
where 
e.DeleteFlag.Equals("n") && 
(

    (!(e.VAT == null || e.VAT.Equals("")) && Clients.Any(f => f.ClientTypeId == 2 && f.VAT.Equals(e.VAT))) 

    || (!(e.Email == null || e.Email.Equals("")) && 
     (
      Clients.Any(f => f.ClientTypeId == 2 && f.Email.ToLower().Equals(e.Email.ToLower())) 
      || (from f in ClientUsers join q in Clients on f.ClientId equals q.Id where f.Email.Equals(e.Email.ToLower()) && q.ClientTypeId == 2 select f.Id).Any() 
     ) 
    ) 

    || (!(u.Email == null || u.Email.Equals("")) && 
     (
      Clients.Any(f => f.ClientTypeId == 2 && f.Email.ToLower().Equals(u.Email.ToLower())) 
      || (from f in ClientUsers join q in Clients on f.ClientId equals q.Id where f.Email.Equals(u.Email.ToLower()) && q.ClientTypeId == 2 select f.Id).Any() 
     ) 
    ) 

) 
select e 

結果:

-- Region Parameters 
DECLARE @p0 VarChar(1) SET @p0 = 'n' 
DECLARE @p1 NVarChar(1) SET @p1 = '' 
DECLARE @p2 Int SET @p2 = 2 
DECLARE @p3 NVarChar(1) SET @p3 = '' 
DECLARE @p4 Int SET @p4 = 2 
DECLARE @p5 Int SET @p5 = 2 
DECLARE @p6 NVarChar(1) SET @p6 = '' 
DECLARE @p7 Int SET @p7 = 2 
DECLARE @p8 Int SET @p8 = 2 
DECLARE @p9 Int SET @p9 = 4 
-- EndRegion 
SELECT [t0].[Id], [t0].[AccountId], [t0].[CompanyName], [t0].[Address], [t0].[Address2], [t0].[PostCode], [t0].[PostArea], [t0].[ContactPerson], [t0].[Phone], [t0].[Email], [t0].[VAT], [t0].[Webpage], [t0].[Description], [t0].[Active], [t0].[PreRegcode], [t0].[PreRegcheck], [t0].[AccountCreated], [t0].[UpdateTimeStamp], [t0].[DeleteFlag], [t0].[ClientTypeId], [t0].[CampaignCodeId], [t0].[PayexId], [t0].[ApiKey], [t0].[InvoiceName], [t0].[Source], [t0].[ProspectStatusId], [t0].[ProspectLastCommentId], [t0].[ProspectCallbackDate] 
FROM [Clients] AS [t0] 
INNER JOIN [ClientUsers] AS [t1] ON ([t0].[Id]) = [t1].[ClientId] 
WHERE ([t0].[DeleteFlag] = @p0) AND (((NOT (([t0].[VAT] IS NULL) OR ([t0].[VAT] = @p1))) AND (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [Clients] AS [t2] 
    WHERE ([t2].[ClientTypeId] = @p2) AND ([t2].[VAT] = [t0].[VAT]) 
    ))) OR ((NOT (([t0].[Email] IS NULL) OR ([t0].[Email] = @p3))) AND ((EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [Clients] AS [t3] 
    WHERE ([t3].[ClientTypeId] = @p4) AND (LOWER([t3].[Email]) = LOWER([t0].[Email])) 
    )) OR (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [ClientUsers] AS [t4] 
    INNER JOIN [Clients] AS [t5] ON [t4].[ClientId] = ([t5].[Id]) 
    WHERE ([t4].[Email] = LOWER([t0].[Email])) AND ([t5].[ClientTypeId] = @p5) 
    )))) OR ((NOT (([t1].[Email] IS NULL) OR ([t1].[Email] = @p6))) AND ((EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [Clients] AS [t6] 
    WHERE ([t6].[ClientTypeId] = @p7) AND (LOWER([t6].[Email]) = LOWER([t1].[Email])) 
    )) OR (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [ClientUsers] AS [t7] 
    INNER JOIN [Clients] AS [t8] ON [t7].[ClientId] = ([t8].[Id]) 
    WHERE ([t7].[Email] = LOWER([t1].[Email])) AND ([t8].[ClientTypeId] = @p8) 
    ))))) AND ([t0].[ClientTypeId] = @p9) 

查詢工作,但需要5分鐘來運行。

+0

過多少數據? – 2009-09-30 08:12:35

+0

54641客戶(每個客戶今天只有一個ClientUser)。類型2的4544和類型4的30287. – 2009-09-30 08:14:57

+0

我認爲,如果您描述表格以及想要完全替代的內容,則會更容易。還要確保你在這些列上有索引。 – Runeborg 2009-09-30 09:19:45

回答

2

你使用的是什麼數據庫排序規則?查詢可以進行重組,簡化了一點,但首先它可能是一個想法,刪除所有.ToLower等等,除非你使用的是區分大小寫的整理...

編輯:你可以嘗試改變你的查詢一些較小的聯合查詢讓sql優化器沒有創造性的自由......(查詢中的許多'或'條件往往會導致掃描,即使有覆蓋索引)。

例如爲:

(

from e in dc.Clients 
join u in dc.ClientUsers on e.Id equals u.ClientId 
join vc in dc.Clients on new { ClientTypeId = 2, e.VAT } equals new { vc.ClientTypeId, vc.VAT } 
where e.ClientTypeId == 4 
    && e.DeleteFlag.Equals("n") 
    && e.VAT != null 
    && e.VAT != "" 
select e 

).Union(

from e in dc.Clients 
join u in dc.ClientUsers on e.Id equals u.ClientId 
join ec in dc.Clients on new { ClientTypeId = 2, e.Email } equals new { ec.ClientTypeId, ec.Email } 
where e.ClientTypeId == 4 
&& e.DeleteFlag.Equals("n") 
&& e.Email != null 
&& e.Email != "" 
select e 

).Union(

from e in dc.Clients 
join u in dc.ClientUsers on e.Id equals u.ClientId 
join c1u in dc.ClientUsers on e.Email equals new c1u.Email 
join c1c in dc.Clients on new { ClientTypeId = 2, c1u.ClientId } equals new { c1c.ClientTypeId, ClientId = c1c.Id } 
where e.ClientTypeId==4 
&& e.DeleteFlag.Equals("n") 
&& e.Email != null 
&& e.Email != "" 
select e 

).Union(

from e in dc.Clients 
join u in dc.ClientUsers on e.Id equals u.ClientId 
join c2u in dc.ClientUsers on u.Email equals c2u.Email 
join c2c in dc.Clients on new { ClientTypeId = 2, c2u.ClientId } equals new { c2c.ClientTypeId, ClientId = c2c.Id } 
where e.ClientTypeId==4 
&& e.DeleteFlag.Equals("n") 
&& u.Email != null 
&& u.Email != "" 
select e 

) 
+0

SQL_SwedishStd_Pref_CP1_CI_AS – 2009-09-30 08:32:56

+3

好的。這是一個不區分大小寫的排序規則,因此您可以刪除.ToLower調用... – KristoferA 2009-09-30 08:34:42

+0

您是優化器專家!刪除ToLower減少了執行到3 sek。但是使用你的聯盟將執行力降低到幾乎沒有! – 2009-09-30 12:17:26