2014-02-26 105 views
0

此查詢需要很長時間才能在具有70GB數據的MS Sql 2008 DB上運行。 如果我單獨運行2 where子句,則需要很多時間。有沒有辦法讓這個查詢更高效的性能?

編輯 - 之後我需要將'select *'更改爲'delete',請在回答時記住它。謝謝:)

select * 
From computers 
Where Name in 
     (
     select T2.Name 
     from 
      (
      select Name 
      from computers 
      group by Name 
      having COUNT(*) > 1 
      ) T3 
     join computers T2 on T3.Name = T2.Name 
     left join policyassociations PA on T2.PK = PA.EntityId 
     where (T2.EncryptionStatus = 0 or T2.EncryptionStatus is NULL) and 
      (PA.EntityType <> 1 or PA.EntityType is NULL) 
    ) 
OR 
     ClientId in 
     (
     select substring(ClientID,11,100) 
     from computers 
    ) 
+2

用存在(子查詢)替換IN(子查詢)(t2和t3從未被外部查詢引用,並且t2和t3具有相同的用途,它們的產品是笛卡爾積。) – wildplasser

回答

0

交換INEXISTS會有所幫助。 此外,根據戈登的回答:UNION可以超越OR

SELECT computers.* 
FROM computers 
LEFT 
    JOIN policyassociations 
    ON policyassociations.entityid = computers.pk 
WHERE (
      computers.encryptionstatus = 0 
     OR computers.encryptionstatus IS NULL 
     ) 
AND (
      policyassociations.entitytype <> 1 
     OR policyassociations.entitytype IS NULL 
     ) 
AND EXISTS (
     SELECT name 
     FROM (
       SELECT name 
       FROM computers 
       GROUP 
        BY name 
       HAVING Count(*) > 1 
       ) As duplicate_computers 
     WHERE name = computers.name 
     ) 

UNION 

SELECT * 
FROM computers As c 
WHERE EXISTS (
     SELECT SubString(clientid, 11, 100) 
     FROM computers 
     WHERE SubString(clientid, 11, 100) = c.clientid 
     ) 

您現在已經更新了您的問題,問使這個刪除。

那麼好消息是,而不是「或」你只是做兩個DELETE聲明:

DELETE 
FROM computers 
LEFT 
    JOIN policyassociations 
    ON policyassociations.entityid = computers.pk 
WHERE (
      computers.encryptionstatus = 0 
     OR computers.encryptionstatus IS NULL 
     ) 
AND (
      policyassociations.entitytype <> 1 
     OR policyassociations.entitytype IS NULL 
     ) 
AND EXISTS (
     SELECT name 
     FROM (
       SELECT name 
       FROM computers 
       GROUP 
        BY name 
       HAVING Count(*) > 1 
       ) As duplicate_computers 
     WHERE name = computers.name 
     ) 
; 

DELETE 
FROM computers As c 
WHERE EXISTS (
     SELECT SubString(clientid, 11, 100) 
     FROM computers 
     WHERE SubString(clientid, 11, 100) = c.clientid 
     ) 
; 
+0

返回以下錯誤 - 消息205,級別16,狀態1,行1 所有使用UNION,INTERSECT或EXCEPT運算符組合的查詢在目標列表中必須具有相同數量的表達式。 – Morrtz

+0

@Morrtz編輯,現在嘗試。我正在懶惰(我不知道表結構)並使用'SELECT *'。您應該*總是*列出您的列 – gvee

+0

我已編輯帖子,並補充說我需要將選擇更改爲刪除後,所以請在回答前檢查,因爲我不能使用聯合。 – Morrtz

0

or有時候可能會很差。在這種情況下,你可以將查詢分爲兩個子查詢和使用union將它們結合起來:

select * 
From computers 
Where Name in 
     (
     select T2.Name 
     from 
      (
      select Name 
      from computers 
      group by Name 
      having COUNT(*) > 1 
      ) T3 
     join computers T2 on T3.Name = T2.Name 
     left join policyassociations PA on T2.PK = PA.EntityId 
     where (T2.EncryptionStatus = 0 or T2.EncryptionStatus is NULL) and 
      (PA.EntityType <> 1 or PA.EntityType is NULL) 
    ) 
UNION 
select * 
From computers 
WHERE ClientId in 
     (
     select substring(ClientID,11,100) 
     from computers 
    ); 

您還可能能夠通過明確join小號取代子查詢來提高性能。但是,這似乎是改善性能的最短途徑。

編輯:

我覺得跟參加的版本是:

select c.* 
From computers c left outer join 
    (select c.Name 
     from (select c.*, count(*) over (partition by Name) as cnt 
      from computers c 
      ) c left join 
      policyassociations PA 
      on T2.PK = PA.EntityId and PA.EntityType <> 1 
     where (c.EncryptionStatus = 0 or c.EncryptionStatus is NULL) and 
      c.cnt > 1 
    ) cpa 
    on c.Name = cpa.Name left outer join 
    (select substring(ClientID, 11, 100) as name 
     from computers 
    ) csub 
    on c.Name = csub.name 
Where cpa.Name is not null or csub.Name is not null; 
+0

運行時出錯 - 消息4104,級別16,狀態1,行8 無法綁定多部分標識符「T2.PK」。 – Morrtz

+0

我編輯了帖子,並補充說我需要將選擇更改爲刪除之後,所以請在回答之前檢查,因爲我無法使用trhe – Morrtz

0

有些事情我想看看是
1.到位索引?
2.'IN'會減慢你的查詢,嘗試用連接替換它,
3.你應該使用列名,在這種情況下,我猜'Name',同時使用count(*),
4.嘗試選擇通過選擇特定的列,僅需要數據。

希望這有助於!

相關問題