Partitioning

查詢訪問更多分區的分區表?

  • December 16, 2020

我第一次在 SO 上發布了這個但沒有得到回复,這就是我現在在這裡嘗試的原因,我希望我這樣做沒有違反任何規則(手指交叉)。

我試圖了解如何正確使用表分區和分區消除,以便我可以決定是否要在新數據庫(sql server 17 express)中使用它。我傾向於不使用它,但這是一個不同的故事,所以這個問題更多的是我現在不知道它是如何工作的。在下面的腳本中,我創建了一個分區函式和方案,一個使用該方案的表,插入一些數據,然後以 3 種不同的方式查詢它。

  • 第一個查詢正確地僅訪問第一個分區(實際分區計數 = 1,實際訪問的分區 = 1)。
  • 我希望第二個查詢也只能訪問第一個分區,因為我已經在值 20200101 上創建了分區函式作為範圍,但它正在訪問分區 1 和 2(實際分區計數 = 2,實際訪問的分區 = 1。 .2)。
  • 我希望第三個查詢只能訪問分區 2,但它正在訪問分區 2 和 3(實際分區計數 = 2,實際訪問的分區 = 2..3)。

我知道我需要進行精確的類型匹配才能進行分區消除,但我想我在這裡有嗎?我錯過了什麼?

create partition function partfun (datetime2(0))
as range right for values ('20200101', '20210101')

create partition scheme ps
as partition partfun all to ([primary])

create table t
(
   id int not null identity(1,1),
   logdate datetime2(0)
) on ps(logdate)
insert into t values ('20190101'),('20200102')

select * from t where logdate < cast('20191231' as datetime2(0))
select * from t where logdate < cast('20200101' as datetime2(0))
select * from t where logdate >= cast('20200101' as datetime2(0)) and t.logdate < cast('20210101' as datetime2(0))

這些瑣碎的查詢會自動參數化。因此,在編譯期間,文字值會被參數替換。使用範圍搜尋謂詞中的內部 RangePartitonNew 函式在執行時動態消除分區。重要的是,搜尋謂詞開始/結束範圍是包容性的,因此可以將相同的記憶體計劃重用於任何可能的值,而不僅僅是查詢中的精確邊界匹配。隨後根據WHERE子句謂詞過濾行以僅返回所需的行。

下面是前 2 個查詢的搜尋謂詞。在執行時,第一個查詢 seek 等同於partition_number >= 1 AND partition_number <= 1,第二個是partition_number >= 1 AND partition_number <= 2. 由於小於運算符,分區 1 被硬編碼為起始範圍。

Seek Keys[1]: 
   Start: PtnId1001 >= Scalar Operator((1)),
   End: PtnId1001 <= Scalar Operator(RangePartitionNew(CONVERT(datetime2(0),[@1],0),(1),'2020-01-01 00:00:00','2021-01-01 00:00:00'))

與第三個查詢的查找謂詞不同之處僅在於起始範圍還包括 RangePartitionNew 以消除大於或等於比較運算符排除的分區。這個 seek 等同於 predicate partition_number >= 2 AND partition_number <= 3

Seek Keys[1]: 
   Start: PtnId1001 >= Scalar Operator(RangePartitionNew(CONVERT(datetime2(0),[@1],0),(1),'2020-01-01 00:00:00','2021-01-01 00:00:00')),
       End: PtnId1001 <= Scalar Operator(RangePartitionNew(CONVERT(datetime2(0),[@2],0),(1),'2020-01-01 00:00:00','2021-01-01 00:00:00'))

您可以使用Paul 部落格文章中的這些技術避免簡單的參數化:

  • 選項(重新編譯)
  • 添加一個虛擬謂詞,例如WHERE 1 <> 2

如果確切的邊界值是您唯一的案例,您可以添加一個謂詞來使用小於比較運算符評估分區函式。這將保留參數化的好處。例如:

AND $PARTITION.partfun(logdate) < $PARTITION.partfun('20200101')

生成的參數化計劃搜尋謂詞從邊界範圍的末尾減去 1,以消除上述謂詞排除的分區:

Seek Keys[1]: 
   Start: PtnId1001 >= Scalar Operator((1)), 
   End: PtnId1001 <= Scalar Operator(RangePartitionNew(CONVERT_IMPLICIT(datetime2(0),[@2],0),(1),'2020-01-01 00:00:00','2021-01-01 00:00:00')-(1))

請注意,分區列上的索引將減少對這些變通方法的需求。即使一個額外的分區會被精確的邊界值所觸及,成本也只是幾個額外的邏輯讀取。

引用自:https://dba.stackexchange.com/questions/281518