2012-06-27 42 views
2

如何重寫這個T-SQL代碼產生相同的結果重寫T-SQL按位邏輯

SELECT ACC.Title, 
      ACC.AdvertiserHierarchyId, 
      1 AS Counter 
    FROM admanAdvertiserHierarchy_tbl ACC 
    JOIN dbo.admanAdvertiserObjectType_tbl AOT ON AOT.AdvertiserObjectTypeId = ACC.AdvertiserObjectTypeId 
       WHERE (EXISTS 
         (SELECT 1 
          FROM dbo.admanAdvertiserHierarchy_tbl CAMP 
          JOIN dbo.admanAdvertiserAdGroup_tbl AG ON CAMP.AdvertiserHierarchyId = AG.AdvertiserHierarchyId 
          JOIN dbo.admanAdvertiserCreative_tbl AC ON AC.AdvertiserAdGroupId = AG.AdvertiserAdGroupId 
          AND  CAMP.ParentAdvertiserHierarchyId = ACC.AdvertiserHierarchyId 
          WHERE CAMP.ERROR = 0 
            AND AC.Dirty & 7 > 0 
            AND AC.ERROR = 0 
            AND AG.ERROR = 0)) 

其阻止優化器有效地利用索引。 努力達到以下效果

Title        AdvertiserHierarchyId  Counter 
    [email protected]  15908      1 
    [email protected]  37887      1 
    [email protected]   37383      1 
    [email protected]   27006      1 
    011         10526      1 
    013         10528      1 
    033         12013      1 
    062         17380      1 
    076         20505      1 

這是骯髒的TINYINT列

Dirty total 
    0  36340607 
    1  117569 
    2  873553 
    3  59 

鏈接到一個靜態的原因表

DirtyReasonId Title 
    0    Nothing 
    1    Overnight Engine 
    2    End To End 
    3    Overnight And End To End 
    4    Pause Resume 
    5    Overnight Engine and Paused 
    6    Overnight Engine E2E and Paused 
    7    All Three 
+0

是@DirtyReason聲明爲BIT?你能否展示一個非常簡短的數據樣本和期望的結果? (這看起來很熟悉:-)) –

+0

存在多少個標記,'Dirty'的數據類型是什麼? –

+0

@aaron的確是它!我正在測試一些重寫的​​存儲過程並沒有得到想要的結果,我想我誤解了按位執行的邏輯 –

回答

3

如果你問具體有關的計數使用BITWISE AND運算符,我相信你是正確的,並且SQL Server不太可能認爲這是可靠的,至少不是帶有髒的索引作爲領先專欄。

您只顯示正在使用的最低兩位(髒的最大值爲3),但您正在測試最低的三位。

因此,AC.Dirty > 0將返回相同的結果,因爲3是Dirty的最大值。但是有可能會設置其他(高位)位,例如Dirty可能會被設置爲8.因此,如果意圖僅檢查最低三位,那麼我們需要確保我們只測試三個最低位。這種表達會做到這一點,和一個謂詞是優化搜索:

(AC.Dirty > 0 AND AC.Dirty % 8 > 0) 

這基本上第一次測試是否AC.Dirty任何位被置,然後如果最後三個位設置檢查。 (我們使用MODULO除法運算符來返回AC.Dirty的剩餘部分除以8,當然這將返回一個介於0和7之間的整數值。如果我們得到一個零,那麼我們知道沒有低三位我們知道至少有一個位被設置

只是要明確:AC.Dirty > 0上的謂詞是多餘的,它包含在這裏,以防止你想確保數據庫至少可以考慮使用與Dirty現有索引作爲前導列。


我會提到另一個值得考慮的選擇將被添加上表達的持續計算列,並在其上創建索引。而T3帽子似乎有點矯枉過正,你需要在這裏。


如果你是有關獲取上表admanAdvertiserCreative_tbl(AC)使用的索引專門詢問,那麼有可能是你最好的人選將是對(AdvertiserAdGroupId, Error, Dirty)覆蓋指數。


下面的SQL重寫應該返回相同的結果,也許是更好的性能(取決於您的數據分發,索引等)

基本上,更換EXISTS(相關子查詢)與JOIN來一個子查詢。子查詢返回CAMP.ParentAdvertiserHierarchyId的不同值,這是您引用的用於關聯子查詢的列。

這可能會也可能不會使用任何索引,具體取決於可用的索引。(很可能已經聚集唯一索引的主鍵,並有外鍵非聚集索引,這將有助於連接性能。)

未經測試:

SELECT ACC.Title, 
     ACC.AdvertiserHierarchyId, 
     1 AS Counter 
FROM admanAdvertiserHierarchy_tbl ACC 
JOIN dbo.admanAdvertiserObjectType_tbl AOT 
     ON AOT.AdvertiserObjectTypeId = ACC.AdvertiserObjectTypeId 
JOIN (SELECT CAMP.ParentAdvertiserHierarchyId 
      FROM dbo.admanAdvertiserHierarchy_tbl CAMP 
      JOIN dbo.admanAdvertiserAdGroup_tbl AG 
      ON CAMP.AdvertiserHierarchyId = AG.AdvertiserHierarchyId 
      JOIN dbo.admanAdvertiserCreative_tbl AC 
      ON AC.AdvertiserAdGroupId = AG.AdvertiserAdGroupId 
     WHERE CAMP.ERROR = 0 
      AND (AC.Dirty > 0 AND AC.Dirty % 8 > 0) 
      AND AC.ERROR = 0 
      AND AG.ERROR = 0) 
     GROUP BY CAMP.ParentAdvertiserHierarchyId 
     ) c 
    ON c.ParentAdvertiserHierarchyId = ACC.AdvertiserHierarchyId 
+0

感謝所有的信息斯賓塞,索引確實存在。這段代碼是使用「髒」表的幾個存在語句的一部分。我在這裏應用了這些建議,但收益僅爲1-2%。我可能會嘗試將表格拆分爲位列。謝謝 –

+0

你有很多連接在那裏。 Dirty列上的謂詞可能不是性能問題。缺少聚簇索引,主鍵索引,外鍵索引和覆蓋索引將成爲「大」問題。 – spencer7593