數據倉儲中的欄儲存索引
適用於:SQL Server
Azure SQL 資料庫
Azure SQL 受控執行個體
Analytics Platform System (PDW)
Microsoft Fabric 中的 SQL 資料庫
列存儲索引結合資料分區,對於構建 SQL Server 資料倉儲非常重要。 本文著重於使用 SQL 資料庫 引擎進行數據倉儲設計的主要使用案例和範例。
資料倉儲的主要功能
SQL Server 2016 (13.x) 導入了這些增強資料行存放區效能的功能:
- Always On 支援在可讀取的次要複本上查詢資料行存放區索引。
- Multiple Active Result Sets (MARS) 支援列存儲索引。
- 全新動態管理檢視 sys.dm_db_column_store_row_group_physical_stats (Transact-SQL) 提供資料列群組層級的效能疑難排解資訊。
- 列存儲索引上的單一執行緒查詢,可以批次模式執行。 以前只有多執行緒查詢可以批次模式執行。
-
SORT
運算子可在批次模式中執行。 - 多個
DISTINCT
運算子可在批次模式中執行。 - 視窗彙總現可在資料庫相容性層級 130 及更高層級的批次模式下執行。
- 使用彙總下推技術可以更有效地處理彙總操作。 支援所有資料庫相容性層級。
- 字串述詞下推可有效處理字串述詞。 支援所有資料庫相容性層級。
- 資料庫相容性等級 130 以上的快照隔離。
- SQL Server 2022 (16.x) 引進已排序的叢集數據行存放區索引。 如需詳細資訊,請參閱 CREATE COLUMNSTORE INDEX 和 使用已排序的數據行存放區索引進行效能微調。 如需已排序的數據行存放區索引可用性,請參閱 已排序的數據行索引可用性。
如需了解 SQL Server 和 Azure SQL 各版本與平台的新功能,請參閱資料行存放區索引的最新功能。
透過結合非叢集和資料行存放區索引來改善效能
從 SQL Server 2016 (13.x) 開始,您可以在叢集數據行存放區索引上定義資料列存放區非叢集索引。
例如:以非叢集索引改善資料表搜尋的效率
若要改善在資料倉儲中搜尋資料表的效率,您可以建立專用的非叢集索引來執行對資料表搜尋有最佳效能的查詢。 例如,針對 B 型樹狀結構索引執行比對值或傳回小範圍值的查詢,其執行效能會比針對資料行存放區索引更佳。 這些索引不需要透過資料行存放區索引進行完整資料表掃描,且透過 B 樹索引進行二元搜尋會更快地傳回正確的結果。
--BASIC EXAMPLE: Create a nonclustered index on a columnstore table.
--Create the table
CREATE TABLE t_account (
AccountKey int NOT NULL,
AccountDescription nvarchar (50),
AccountType nvarchar(50),
UnitSold int
);
GO
--Store the table as a columnstore.
CREATE CLUSTERED COLUMNSTORE INDEX taccount_cci ON t_account;
GO
--Add a nonclustered index.
CREATE UNIQUE INDEX taccount_nc1 ON t_account (AccountKey);
範例:使用非叢集索引在資料列存放區資料表上設置主索引鍵條件約束。
根據設計,資料行存放區資料表不允許叢集主索引鍵限制式。 現在您可以在資料行存放區資料表上使用非叢集索引來施加主鍵約束。 在非 NULL 的資料行上主索引鍵等同 UNIQUE 條件約束,而且 SQL Server 會實作 UNIQUE 條件約束來當作非叢集索引。 結合這些事實,以下範例在非 NULL 資料行 accountkey 上定義 UNIQUE 條件約束。 結果是一個非叢集索引,它將主鍵約束作為非 NULL 資料行上的 UNIQUE 約束。
接下來,該資料表會轉換為叢集資料行存放區索引。 轉換期間會保留非叢集索引。 結果是一個叢集資料行存放區索引,並帶有一個強制執行主索引鍵約束的非叢集索引。 因為資料行存放區資料表上的任何更新或插入都會影響非叢集索引,所以任何違反唯一性限制式和非 NULL 的作業都會造成整個作業失敗。
結果是一個包含強制在兩個索引上執行主索引鍵條件約束之非叢集索引的資料行存放區索引。
--EXAMPLE: Enforce a primary key constraint on a columnstore table.
--Create a rowstore table with a unique constraint.
--The unique constraint is implemented as a nonclustered index.
CREATE TABLE t_account (
AccountKey int NOT NULL,
AccountDescription nvarchar (50),
AccountType nvarchar(50),
UnitSold int,
CONSTRAINT uniq_account UNIQUE (AccountKey)
);
--Store the table as a columnstore.
--The unique constraint is preserved as a nonclustered index on the columnstore table.
CREATE CLUSTERED COLUMNSTORE INDEX t_account_cci ON t_account
--By using the previous two steps, every row in the table meets the UNIQUE constraint
--on a non-NULL column.
--This has the same end-result as having a primary key constraint
--All updates and inserts must meet the unique constraint on the nonclustered index or they will fail.
--If desired, add a foreign key constraint on AccountKey.
ALTER TABLE [dbo].[t_account]
WITH CHECK ADD FOREIGN KEY([AccountKey]) REFERENCES my_dimension(Accountkey);
藉由啟用資料列層級和資料列群組層級鎖定來改善效能
為了補充資料行存放區索引功能上的非叢集索引,SQL Server 2016 (13.x) 提供選取、更新與刪除作業的詳細鎖定功能。 查詢能夠針對非叢集索引在索引搜尋上以資料列層級鎖定執行,或針對資料行存放區索引在完整資料表掃描上以資料行群組層級鎖定執行。 藉由適當地使用資料列層級和資料列群組層級鎖定,達到更高的讀寫並行性。
--Granular locking example
--Store table t_account as a columnstore table.
CREATE CLUSTERED COLUMNSTORE INDEX taccount_cci ON t_account
GO
--Add a nonclustered index for use with this example
CREATE UNIQUE INDEX taccount_nc1 ON t_account (AccountKey);
GO
--Look at locking with access through the nonclustered index
SET TRANSACTION ISOLATION LEVEL repeatable read;
GO
BEGIN TRAN
-- The query plan chooses a seek operation on the nonclustered index
-- and takes the row lock
SELECT * FROM t_account WHERE AccountKey = 100;
COMMIT TRAN
快照隔離和讀取提交快照隔離
使用快照隔離(SI)來保證交易一致性,並使用讀提交快照隔離(RCSI)來保證列存索引查詢的語句層級一致性。 這可讓查詢執行而不會封鎖資料寫入器。 此非封鎖性的行為也會大幅降低複雜交易發生死結的可能性。 如需詳細資訊,請參閱 SQL Server 中的快照隔離。