Sql-Server

在列儲存索引掃描運算符之前消除篩選運算符

  • September 23, 2020

我有一個包含數百萬行的大型事實表,稱為 MyLargeFactTable,它是一個聚集列儲存表。

那裡也有一個複合主鍵約束(customer_id、location_id、order_date 列)。

我還有一個臨時表#my_keys_to_filter_MyLargeFactTable,具有完全相同的 3 列,它包含這 3 個鍵值的幾千個唯一組合。

下面的查詢給了我想要的結果集

...
FROM #my_keys_to_filter_MyLargeFactTable AS t
JOIN dbo.MyLargeFactTable AS m
ON m.customer_id = t.customer_id
AND m.location_id = t.location_id
AND m.order_date = t.order_date

但我注意到事實表上的索引掃描運算符返回的行數超過了它應該返回的行數(大約一百萬)並將其輸入過濾器運算符,這進一步將結果集減少到所需的幾千行。

在此處輸入圖像描述

索引掃描運算符讀取大量行(它們非常寬的行)增加 IO,並顯著減慢整個查詢。

我的參數不是 sargable 嗎?

如何刪除過濾器運算符並以某種方式強制索引掃描運算符只讀取幾千行?

表定義:

create table #my_keys_to_filter_MyLargeFactTable 
(
customer_id varchar(96) not null,
location_id varchar(96) not null,
order_date date not null,
primary key clustered (customer_id,location_id,order_date)
)

create table MyLargeFactTable
(
customer_id varchar(96) not null,
location_id varchar(96) not null,
order_date date not null,
...
lot of wide decimal typed columns, and even large varchars
...
PRIMARY KEY NONCLUSTERED  (customer_id,location_id,order_date),
INDEX cci CLUSTERED COLUMNSTORE
)

如何刪除過濾器運算符並以某種方式強制索引掃描運算符只讀取幾千行?

Filter 操作符在散列連接處應用建立在連接列上的點陣圖。

在三個連接謂詞中,只有order_date一種數據類型支持點陣圖下推到列儲存掃描。如果您查看掃描中的謂詞,您應該會看到如下內容:

PROBE([Opt_Bitmap1005],[dbo].[MyLargeFactTable].[order_date])

其餘的連接謂詞是字元串,因此將作為完整點陣圖測試的一部分出現在過濾器中:

PROBE([Opt_Bitmap1005],
   [dbo].[MyLargeFactTable].[customer_id],
   [dbo].[MyLargeFactTable].[location_id],
   [dbo].[MyLargeFactTable].[order_date])

將點陣圖測試(部分)推送到列儲存掃描中是一種優化,僅適用於可以容納 64 位的數據類型(如date您的範例中)。注意連接點陣圖下推不同於字元串謂詞下推(例如 push customer_id LIKE '%XYZ%')。

有幾種方法可以解決這個限制。重新設計架構,以便將長字元串移動到維度表並使用整數鍵進行引用是一種選擇。

稍微不那麼侵入性,您可以將整數添加checksum到列儲存(遺憾的是不是作為持久計算列)和臨時表,然後將其添加到連接中 - 例如計算自CHECKSUM(customer_id, location_id, order_date)等的整數。

仍然會有一個過濾器,但點陣圖將包括校驗和列,可以將其推送到掃描中。這應該會顯著減少傳遞給過濾器的行數。

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