SQL Server 2012 內部連接估計行數問題
我有一個簡單的連接,如下所示:
select * from fact_sales f join dim_company d on f.company_SK = d.company_SK
事實表包含大約 5 億多條記錄(使用 NC 列儲存),查詢將返回所有記錄,但是估計連接後的行數僅為 3 億。直到雜湊連接,估計的行數是正確的,只有在連接後才下降到 3 億。這是查詢的估計計劃:
我已經更新了事實表(使用全掃描)和維度表中連接中使用的 SK 列的統計資訊,這是每個的直方圖:
這個問題似乎只發生在數據庫中的幾個維度表上,加入其他維度表不會產生相同類型的基數估計問題 - 關於如何解決這個問題或進一步調查的任何建議?
如果我在查詢中添加 where 子句,它會正確估計連接之前/之後的行數,例如
select * from fact_sales f join dim_company d on f.company_SK = d.company_SK where company_SK = 1
將估計從連接中出來的 467,583,000 行,這與直方圖中的內容相匹配。
該問題似乎僅在我在查詢中沒有任何過濾器時發生。它在更大的查詢中導致問題(排序溢出)。我已將其縮小到這個特定的連接。
我確實有一個 FK 約束,但它們已在事實表上被關閉 (
WITH NOCHECK
)(我們被告知關閉它們,以便 ETL 可以更快地執行)。不幸的是,不能重新打開 FK :(更新:啟用跟踪標誌 2301 解決了問題:p
我能夠在啟用舊版 CE 和 TF 4199 的 SQL Server 2014 中重現您的問題。我使用了行儲存事實表,因為我對列儲存幾乎沒有經驗。
對於使用過濾器的查詢,查詢優化器將查詢重寫為如下內容:
select * from fact_sales f join dim_company d on f.company_SK = d.company_SK where f.company_SK = 1 and d.company_SK = 1
對於該查詢,優化器可以直接對兩個表使用包含 1 的直方圖步驟,並且您得到 467,583,000 X 1 作為估計的行數。
沒有過濾器的查詢將使用線性插值:
對於具有單個等式或不等式謂詞的連接,舊版 CE 通過使用線性插值逐步對齊兩個直方圖來連接連接列上的直方圖。
請注意,維度表的統計資訊沒有 RANGE_HI_KEY 值為 1 的直方圖步驟,這是事實表中幾乎所有數據的位置。該值的線性插值步驟出了點問題。如果我創建的維度表沒有 0 值,那麼直方圖將獲得一個 RANGE_HI_KEY 值為 1 的步驟。這可以修復估計值。簡而言之,您的直方圖不走運。我認為沒有一種受支持的方法可以強制維度表上的直方圖包含 1 的步驟,除非您可能願意在查詢中添加其他過濾器。
我不知道你的數據的確切規則,但我可以給你兩個解決方法。第一個解決方法是為查詢啟用跟踪標誌 2301。這修復了這部分查詢的估計值,但可能會對查詢的其餘部分產生其他負面影響。此跟踪標誌由 MS記錄,但在使用前請諮詢您的 DBA。
第二種解決方法是鼓勵查詢優化器對連接使用不同的基數估計方法。以下查詢為我提供了一個很好的估計,並且只對您的事實表進行了一次掃描:
select * from FACT_SALES f join (SELECT COMPANY_SK FROM DIM_COMPANY UNION SELECT 1) d on f.company_SK = d.company_SK;