共用方式為


CREATE COLUMNSTORE INDEX (Transact-SQL)

適用於:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse Analytics分析平台系統(PDW)Microsoft Fabric 中的 SQL 資料庫

將數據列存放區數據表轉換成叢集數據行存放區索引,或建立非叢集數據行存放區索引。 使用數據行存放區索引,有效率地在 OLTP 工作負載上執行即時作業分析,或改善數據倉儲工作負載的數據壓縮和查詢效能。

請遵循數據 行存放區索引的新功能 ,以取得這項功能的最新改善。

  • 已排序的叢集數據行存放區索引是在 SQL Server 2022 (16.x) 中引進的。 如需詳細資訊,請參閱 CREATE COLUMNSTORE INDEX。 如需了解有序的資料行存放庫索引的可用性,請參閱 資料行存放庫索引:概觀

  • 從 SQL Server 2016 (13.x) 開始,您可以將資料表建立為叢集數據行存放區索引。 您不再需要先建立數據列存放區數據表,然後將它轉換成叢集數據行存放區索引。

  • 如需資料行存放區索引設計指導方針的相關資訊,請參閱 資料行存放區索引 - 設計指引

Transact-SQL 語法慣例

Syntax

Azure SQL Database 和 Azure SQL 受控實例AUTD 的語法:

-- Create a clustered columnstore index on disk-based table.
CREATE CLUSTERED COLUMNSTORE INDEX index_name
    ON { database_name.schema_name.table_name | schema_name.table_name | table_name }
    [ ORDER (column [ , ...n ] ) ]
    [ WITH ( <with_option> [ , ...n ] ) ]
    [ ON <on_option> ]
[ ; ]

-- Create a nonclustered columnstore index on a disk-based table.
CREATE [ NONCLUSTERED ]  COLUMNSTORE INDEX index_name
    ON { database_name.schema_name.table_name | schema_name.table_name | table_name }
        ( column  [ , ...n ] )
    [ ORDER (column [ , ...n ] ) ]
    [ WHERE <filter_expression> [ AND <filter_expression> ] ]
    [ WITH ( <with_option> [ , ...n ] ) ]
    [ ON <on_option> ]
[ ; ]

<with_option> ::=
      DROP_EXISTING = { ON | OFF } -- default is OFF
    | MAXDOP = max_degree_of_parallelism
    | ONLINE = { ON | OFF }
    | COMPRESSION_DELAY  = { 0 | delay [ MINUTES ] }
    | DATA_COMPRESSION = { COLUMNSTORE | COLUMNSTORE_ARCHIVE }
      [ ON PARTITIONS ( { partition_number_expression | range } [ , ...n ] ) ]

<on_option>::=
      partition_scheme_name ( column_name )
    | filegroup_name
    | "default"

<filter_expression> ::=
      column_name IN ( constant [ , ...n ]
    | column_name { IS | IS NOT | = | <> | != | > | >= | !> | < | <= | !< } constant )

SQL Server 的語法:

-- Create a clustered columnstore index on disk-based table.
CREATE CLUSTERED COLUMNSTORE INDEX index_name
    ON { database_name.schema_name.table_name | schema_name.table_name | table_name }
    [ WITH ( <with_option> [ , ...n ] ) ]
    [ ORDER (column [ , ...n ] ) ]
    [ ON <on_option> ]
[ ; ]

-- Create a nonclustered columnstore index on a disk-based table.
CREATE [ NONCLUSTERED ]  COLUMNSTORE INDEX index_name
    ON { database_name.schema_name.table_name | schema_name.table_name | table_name }
        ( column  [ , ...n ] )
    [ ORDER (column [ , ...n ] ) ]
    [ WHERE <filter_expression> [ AND <filter_expression> ] ]
    [ WITH ( <with_option> [ , ...n ] ) ]
    [ ON <on_option> ]
[ ; ]

<with_option> ::=
      DROP_EXISTING = { ON | OFF } -- default is OFF
    | MAXDOP = max_degree_of_parallelism
    | ONLINE = { ON | OFF }
    | COMPRESSION_DELAY  = { 0 | delay [ MINUTES ] }
    | DATA_COMPRESSION = { COLUMNSTORE | COLUMNSTORE_ARCHIVE }
      [ ON PARTITIONS ( { partition_number_expression | range } [ , ...n ] ) ]

<on_option>::=
      partition_scheme_name ( column_name )
    | filegroup_name
    | "default"

<filter_expression> ::=
      column_name IN ( constant [ , ...n ]
    | column_name { IS | IS NOT | = | <> | != | > | >= | !> | < | <= | !< } constant )

Azure Synapse Analytics 和分析平台系統的語法(PDW):

CREATE CLUSTERED COLUMNSTORE INDEX index_name
    ON { database_name.schema_name.table_name | schema_name.table_name | table_name }
    [ ORDER ( column [ , ...n ] ) ]
    [ WITH ( DROP_EXISTING = { ON | OFF } ) ] -- default is OFF
[;]

版本可用性

某些選項不適用於所有資料庫引擎版本。 下表顯示叢集數據行存放區和非叢集數據行存放區索引中引進選項時的版本:

Option CLUSTERED NONCLUSTERED
COMPRESSION_DELAY SQL Server 2016 (13.x) SQL Server 2016 (13.x)
DATA_COMPRESSION SQL Server 2016 (13.x) SQL Server 2016 (13.x)
ONLINE SQL Server 2019 (15.x) SQL Server 2017 (14.x)
WHERE 子句 N/A SQL Server 2016 (13.x)
ORDER 子句 SQL Server 2016 (13.x) SQL Server 2025 (17.x)

所有選項都可在 Azure SQL Database 和 Azure SQL 受控實例AUTD 中使用。

如需功能可用性的詳細資訊,請參閱 數據行存放區索引的新功能

Arguments

建立叢集列存儲索引

建立叢集數據行存放區索引,其中所有數據都會由數據行壓縮和儲存。 索引包含數據表中的所有資料行,並儲存整個數據表。 如果現有的資料表是堆積或叢集索引,則會轉換成叢集資料行存放區索引。 如果數據表已儲存為叢集數據行存放區索引,則會卸除現有的索引並重建。

Important

在 Fabric 中的 SQL 資料庫中,叢集數據行存放區索引必須在與其所屬數據表相同的批次或交易內建立。 在建立叢集數據行存放區索引之後,將叢集數據行存放區索引加入數據表可能會導致下列錯誤:

Msg 35354, Level 16, State 1, Line 63, The statement failed because a clustered columnstore index cannot be created on a table enabled for Change Feed. Consider disabling Change Feed and then creating the clustered columnstore index.

index_name

指定新索引的名稱。

如果數據表已經有叢集資料行存放區索引,您可以指定與現有索引相同的名稱,也可以使用DROP EXISTING 選項來指定新的名稱。

ON [ database_name。 [ schema_name ] 。 | schema_name 。 ] table_name

指定要儲存為叢集數據行存放區索引之數據表的一部分、二部分或三部分名稱。 如果數據表是堆積或具有叢集索引,則數據表會從數據列存放區轉換成數據行存放區。 如果數據表已經是數據行存放區,此語句會重建叢集數據行存放區索引。

叢集數據行存放區的 ORDER

column_store_order_ordinal使用 sys.index_columns 中的數據行來判斷叢集數據行存放區索引的數據行順序。 數據行存放區排序有助於 區段消除,特別是字串數據。 如需詳細資訊,請參閱使用 已排序的資料行存放區索引進行效能調整資料行存放區索引 - 設計指引

若要轉換成已排序的叢集數據行存放區索引,現有的索引必須是叢集數據行存放區索引。 使用 DROP_EXISTING 選項。

LOB 資料類型 (max) 長度數據類型不能是已排序叢集數據行存放區索引的索引鍵。

建立已排序的叢集數據行存放區索引時,請使用 MAXDOP = 1 選項進行最高品質的排序,以換取語句持續時間 CREATE INDEX 相當長的時間。 若要儘快建立索引,請勿限制 MAXDOP。 壓縮和排序的最高質量有助於數據行存放區索引的查詢。

如需了解有序的資料行存放庫索引的可用性,請參閱 資料行存放庫索引:概觀

WITH 選項

DROP_EXISTING = [OFF] |上

DROP_EXISTING = ON 會指定卸除現有的索引,並建立新的數據行存放區索引。

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines WITH (DROP_EXISTING = ON);

默認值 DROP_EXISTING = OFF,預期索引名稱與現有名稱相同。 如果指定的索引名稱已經存在,就會發生錯誤。

MAXDOP = max_degree_of_parallelism

此選項可以在索引作業期間覆寫現有的平行處理原則伺服器組態。 使用 MAXDOP來限制平行計劃執行中使用的處理器數目。 最大值為64個處理器。

max_degree_of_parallelism 值可以是:

  • 1,這表示隱藏平行計劃產生。
  • >1,這表示根據目前的系統工作負載,將平行索引作業中使用的處理器數目上限限製為指定的數目,或更少。 例如,當 MAXDOP = 4 時,使用的處理器數目是 4 或更少。
  • 0 (預設值),這表示根據目前的系統工作負載,使用實際處理器數目或更少。
CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines WITH (MAXDOP = 2);

如需詳細資訊,請參閱 伺服器組態:平行處理原則的最大程度,以及 設定平行索引作業

COMPRESSION_DELAY = 0 | 延遲 [ 分鐘 ]

如果是磁碟數據表, 延遲 會指定差異數據列群組在關閉狀態中必須保留在差異數據列群組中的最小分鐘數。 SQL Server 接著可以將它壓縮成壓縮的數據列群組。 由於磁碟數據表不會追蹤個別數據列的插入和更新時間,因此 SQL Server 會將延遲套用至處於關閉狀態的差異數據列群組。

預設值是 0 分鐘。

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines WITH (COMPRESSION_DELAY = 10 MINUTES);

如需何時使用 COMPRESSION_DELAY 的建議,請參閱開始 使用資料行存放區索引進行即時作業分析

DATA_COMPRESSION = COLUMNSTORE |COLUMNSTORE_ARCHIVE

針對指定的資料表、分割區編號或分割區範圍指定資料壓縮選項。 選項如下:

  • COLUMNSTORE 是預設值,並指定使用效能最高的數據行存放區壓縮進行壓縮。 此選項是典型的選擇。
  • COLUMNSTORE_ARCHIVE 進一步將數據表或分割區壓縮為較小的大小。 針對封存等情況,請使用此選項,這需要較小的記憶體大小,而且可以承受更多時間來儲存和擷取。
CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines WITH (DATA_COMPRESSION = COLUMNSTORE_ARCHIVE);

如需壓縮的詳細資訊,請參閱資料壓縮 (機器翻譯)

ONLINE = [ON |OFF]
  • ON 會指定數據行存放區索引會維持在在線且可供使用,同時正在建置索引的新複本。
  • OFF 指定在建置新複本時無法使用索引。
CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines WITH (ONLINE = ON);

ON 選項

使用這些選項,您可以指定資料記憶體的選項,例如數據分割配置、特定檔案群組或預設檔案群組。 如果未指定 ON 選項,索引會使用現有資料表的設定分割區或檔案群組設定。

partition_scheme_namecolumn_name ) 會指定資料表的數據分割配置。 分割區配置必須已存在於資料庫中。 若要建立分割區配置,請參閱 CREATE PARTITION SCHEME

column_name 指定分割索引分割的數據行。 此資料行必須符合 partition_scheme_name 所使用資料分割函數引數的資料類型、長度與有效位數。

filegroup_name 指定用來儲存叢集數據行存放區索引的檔案群組。 如果未指定任何位置且數據表未分割,索引會使用與基礎表或檢視表相同的檔案群組。 檔案群組必須已經存在。

若要在預設檔案群組上建立索引,請使用 "default"[default]。 如果您指定 "default",則 QUOTED_IDENTIFIER 選項必須為 ON 目前工作階段。 QUOTED_IDENTIFIER 預設為 ON。 如需詳細資訊,請參閱 SET QUOTED_IDENTIFIER

建立 [非叢集] 資料行存放區索引

在儲存為堆積或叢集索引的數據列存放區數據表上建立非叢集數據行存放區索引。 索引可以有篩選條件,而且不需要包含基礎表的所有數據行。 數據行存放區索引需要足夠的空間來儲存數據的複本。 您可以更新索引,並在基礎表變更時加以更新。 叢集索引上的非叢集數據行存放區索引可即時分析。

index_name

指定索引的名稱。 index_name 在數據表內必須是唯一的,但不需要在資料庫中是唯一的。 索引名稱必須遵循 識別碼的規則。

資料行 [ ,...n ]

指定要儲存的數據行。 非叢集數據行存放區索引限制為1,024個數據行。

每個數據行都必須是數據行存放區索引支持的數據類型。 如需支持的數據類型清單,請參閱 限制和限制

ON [ database_name。 [ schema_name ] 。 | schema_name 。 ] table_name

指定包含索引之數據表的一部分、二部分或三部分名稱。

非叢集數據行存放區的 ORDER

非叢集數據行存放區索引子句中指定的 ORDER 數據行必須是索引之索引之索引鍵數據行的子集。

column_store_order_ordinal使用 sys.index_columns 中的數據行來判斷非叢集數據行存放區索引的數據行順序。 數據行存放區排序有助於 區段消除,特別是字串數據。 如需詳細資訊,請參閱使用 已排序的資料行存放區索引進行效能調整資料行存放區索引 - 設計指引。 這些文章中的設計和效能考慮通常同時適用於叢集和非叢集數據行存放區索引。

LOB 資料類型 (max) 長度數據類型不能是已排序的非叢集數據行存放區索引的索引鍵。

建立已排序的非叢集數據行存放區索引時,請使用 MAXDOP = 1 品質最高的排序選項,以換取語句持續時間 CREATE INDEX 相當長的時間。 若要儘快建立索引,請勿限制 MAXDOP。 壓縮和排序的最高質量有助於數據行存放區索引的查詢。

如需已排序的數據行存放區索引可用性,請參閱 已排序的數據行索引可用性

WITH 選項

DROP_EXISTING = { 關閉 |在 }

  • DROP_EXISTING = 開啟

    現有的索引會卸除並重建。 指定的索引名稱必須與目前現有的索引相同;不過,可以修改索引定義。 例如,您可以指定不同的資料行或索引選項。

  • DROP_EXISTING = 關閉

    如果指定的索引名稱已經存在,就會顯示錯誤。 無法使用 DROP_EXISTING 來變更索引類型。 在回溯相容語法中,WITH DROP_EXISTING相當於WITH DROP_EXISTING = ON。

MAXDOP = max_degree_of_parallelism

覆寫 伺服器組態:索引作業期間平行處理原則組態選項的最大程度 。 使用 MAXDOP來限制平行計劃執行中使用的處理器數目。 最大值為64個處理器。

max_degree_of_parallelism 值可以是:

  • 1,這表示隱藏平行計劃產生。
  • >1,這表示根據目前的系統工作負載,將平行索引作業中使用的處理器數目上限限製為指定的數目,或更少。 例如,當 MAXDOP = 4 時,使用的處理器數目是 4 或更少。
  • 0 (預設值),這表示根據目前的系統工作負載使用實際處理器數目或更少數目。

如需詳細資訊,請參閱 設定平行索引作業。

Note

Microsoft SQL Server 的每個版本都無法使用平行索引作業。 如需 SQL Server 版本支援的功能清單,請參閱 SQL Server 2022 的版本和支援功能

ONLINE = [ON |OFF]
  • ON 會指定數據行存放區索引會維持在在線且可供使用,同時正在建置索引的新複本。
  • OFF 指定在建置新複本時無法使用索引。 在非叢集索引中,基表仍可供使用。 只有在新索引完成之前,才會使用非叢集數據行存放區索引來滿足查詢。
CREATE COLUMNSTORE INDEX ncci
    ON Sales.OrderLines(StockItemID, Quantity, UnitPrice, TaxRate) WITH (ONLINE = ON);
COMPRESSION_DELAY = 0 | 延遲 [ 分鐘 ]

指定數據列應該停留在差異數據列群組中的下限,然後才有資格移轉至壓縮的數據列群組。 例如,您可以說,如果數據列未變更 120 分鐘,該數據列就有資格壓縮成單欄儲存格式。

對於磁碟數據表上的數據行存放區索引,不會追蹤插入或更新數據列的時間。 相反地,差異數據列群組關閉時間會當做數據列的 Proxy 使用。 默認持續時間為 0 分鐘。 在差異資料列群組中累積 1,000,000,000 個資料列之後,資料列會移轉至資料行儲存體,並標示為已關閉。

DATA_COMPRESSION

針對指定的資料表、分割區編號或分割區範圍指定資料壓縮選項。 僅適用於數據行存放區索引,包括非叢集和叢集。 選項如下:

  • COLUMNSTORE 是預設值,並指定使用效能最高的數據行存放區壓縮進行壓縮。 此選項是典型的選擇。
  • COLUMNSTORE_ARCHIVE 進一步將數據表或分割區壓縮為較小的大小。 您可以將此選項用於封存,或針對需要較小記憶體大小的其他情況,而且可以承受更多時間來儲存和擷取。

如需壓縮的詳細資訊,請參閱資料壓縮 (機器翻譯)

其中 <filter_expression> [ 和 <filter_expression> ]

這個選項稱為篩選述詞,指定要包含在索引中的數據列。 SQL Server 會在篩選索引中的數據列上建立篩選的統計數據。

篩選述詞會使用簡單的比較邏輯。 NULL使用常值的比較不允許與比較運算元搭配使用。 IS NULL請改用和 IS NOT NULL 運算符。

以下是資料表的篩選述 Production.BillOfMaterials 詞的一些範例:

  • WHERE StartDate > '20000101' AND EndDate <= '20000630'
  • WHERE ComponentID IN (533, 324, 753)
  • WHERE StartDate IN ('20000404', '20000905') AND EndDate IS NOT NULL

如需已篩選索引的指引,請參閱 建立篩選的索引

ON 選項

下列選項會指定建立索引的檔案群組。

partition_scheme_namecolumn_name

指定數據分割配置,此配置會定義數據分割索引的數據分割所對應的檔案群組。 數據分割配置必須藉由執行 CREATE PARTITION SCHEME 存在於資料庫中。

column_name 指定分割索引分割的數據行。 此資料行必須符合 partition_scheme_name 所使用資料分割函數引數的資料類型、長度與有效位數。 「column_name」不限定為索引定義中的資料行。 分割數據行存放區索引時,如果尚未指定數據行,Database Engine 會將數據分割數據行新增為索引的數據行。

如果數據表已分割,且未指定 partition_scheme_name檔案群組 ,則索引會放在相同的數據分割配置中,並使用與基礎表相同的數據分割數據行。

數據分割數據表上的數據行存放區索引必須對齊數據分割。 如需分割索引的詳細資訊,請參閱 分割數據表和索引

filegroup_name

指定要在其中建立索引的檔案組名。 如果未指定 filegroup_name ,而且數據表並未分割,索引會使用與基礎表相同的檔案群組。 檔案群組必須已經存在。

"default"

在預設檔案群組上建立指定的索引。

在此內容中,預設字詞不是關鍵詞。 它是預設檔案群組的識別碼,並必須以分隔符號括起,例如 ON "default"ON [default]。 如果 "default" 指定了 ,則目前會話的 QUOTED_IDENTIFIER 選項必須是 ON,這是預設設定。 如需詳細資訊,請參閱 SET QUOTED_IDENTIFIER

Permissions

需要資料表上的 ALTER 權限。

Remarks

您可以在臨時表上建立資料行存放區索引。 卸除數據表或會話結束時,也會卸除索引。

在 Fabric SQL 資料庫中,具有叢集資料行存放區索引的資料表不會 鏡像至 Fabric OneLake

篩選的索引

篩選的索引是優化的非叢集索引,適合從數據表中選取少量數據列的查詢。 它會使用篩選述詞來編製數據表中部分數據的索引。 設計良好的篩選索引可以改善查詢效能、降低記憶體成本,以及降低維護成本。

篩選索引的必要SET選項

每當發生下列任一情況時,都需要必要值數據行中的 SET 選項:

  • 您可以建立篩選的索引。
  • INSERT、UPDATE、DELETE 或 MERGE 作業會修改篩選索引中的數據。
  • 查詢優化器會使用篩選的索引來產生查詢計劃。
SET 選項 必填值 預設伺服器值 預設 OLE DB 和 ODBC 值 預設 DB-Library 值
ANSI_NULLS ON ON ON OFF
ANSI_PADDING ON ON ON OFF
ANSI_WARNINGS 1 ON ON ON OFF
ARITHABORT ON ON OFF OFF
CONCAT_NULL_YIELDS_NULL ON ON ON OFF
NUMERIC_ROUNDABORT OFF OFF OFF OFF
QUOTED_IDENTIFIER ON ON ON OFF

1 當資料庫相容性層級設定為 90 或更新版本時,將 ANSI_WARNINGS 設定為 ON,以隱含方式將 ARITHABORT 設定為 ON。 如果資料庫相容性層級設定為 80 或更早版本,您必須將 ARITHABORT 選項明確設定為 ON。

如果 SET 選項不正確,可能會發生下列情況:

  • 未建立篩選的索引。

  • Database Engine 會產生錯誤,並回復變更索引中數據的 INSERT、UPDATE、DELETE 或 MERGE 語句。

  • 查詢優化器不會考慮任何 Transact-SQL 語句的執行計劃中索引。

如需已篩選索引的詳細資訊,請參閱 建立篩選的索引

局限性

資料存放區索引中的每個資料列都必須是下列其中一個常見的商務資料類型:

  • datetimeoffset [ ( n ) ]
  • datetime2 [ ( n ) ]
  • datetime
  • smalldatetime
  • date
  • time [ ( n ) ]
  • float [ ( n ) ]
  • real [ ( n ) ]
  • decimal [ ( precision [ , scale ] ] ]
  • numeric [ ( precision [ , scale ] ] ]
  • money
  • smallmoney
  • bigint
  • int
  • smallint
  • tinyint
  • bit
  • nvarchar [ ( n ) ]
  • nvarchar(max)1
  • nchar [ ( n ) ]
  • varchar [ ( n ) ]
  • varchar(max)1
  • char [ ( n ) ]
  • varbinary [ ( n ) ]
  • varbinary(max)1
  • binary [ ( n ) ]
  • uniqueidentifier2

1 僅適用於叢集資料行存放區索引中的 SQL Server 2017 (14.x),以及進階層、標準層(S3 和更新版本)和所有虛擬核心供應專案層。

2 適用於 SQL Server 2014 (12.x) 和更新版本。

如果基礎表具有數據行存放區索引不支援的數據類型數據行,您必須從非叢集數據行存放區索引中省略該數據行。

大於 8 KB 的大型物件 (LOB) 資料會儲存在 off-row、LOB 記憶體中,而只有儲存在數據行區段內實體位置的指標。 儲存的數據大小不會報告在 sys.column_store_segmentssys.column_store_dictionariessys.dm_db_column_store_row_group_physical_stats中。

使用下列任何資料類型的資料列不能包含在資料列存放區索引中:

  • ntexttextimage
  • nvarchar(max)varchar(max)varbinary(max)1
  • rowversion (和 timestamp
  • sql_variant
  • CLR 類型 (hierarchyid 和空間類型)
  • xml
  • uniqueidentifier2

1 適用於 SQL Server 2016 (13.x) 和舊版,以及非叢集數據行存放區索引。

2 適用於 SQL Server 2012 (11.x)。

非叢集資料行存放區索引:

  • 不能超過 1,024 個數據行。
  • 無法建立為條件約束式索引。 在具有數據行存放區索引的數據表上,可以有唯一的條件約束、主鍵條件約束和外鍵條件約束。 條件約束一律會使用數據列存放區索引強制執行。 使用數據行存放區 (clustered 或 nonclustered) 索引無法強制執行條件約束。
  • 不能包含疏鬆數據行。
  • 無法使用 ALTER INDEX 語句來變更。 若要變更非叢集索引,您必須卸除並重新建立數據行存放區索引。 您可以使用 ALTER INDEX 來停用和重建資料行存放區索引。
  • 無法使用 INCLUDE 關鍵詞來建立。
  • 無法在索引數據列清單中指定 ASCDESC 關鍵詞。 數據行存放區索引會根據壓縮演算法排序。
  • 在 Azure SQL 資料庫中,Microsoft Fabric 中的 SQL 資料庫、Azure SQL Managed InstanceAUTD 以及 SQL Server 2025(17.x)可依包含 ORDER 子句排序。 如需詳細資訊,請參閱使用已排序的數據行存放區索引 效能微調
  • 無法在非叢集數據行存放區索引中包含 nvarchar(max)varchar(max)varbinary(max) 類型的 LOB 數據行。 只有叢集數據行存放區索引支援LOB類型,從SQL Server 2017 (14.x) 版本開始,Azure SQL Database(設定於進階層、標準層 (S3 和更新版本),以及所有虛擬核心供應專案層。 舊版不支援叢集和非叢集數據行存放區索引中的LOB類型。
  • 從 SQL Server 2016 (13.x) 開始,您可以在索引檢視表上建立非叢集數據行存放區索引。

資料存放區索引無法與下列功能結合:

  • 計算資料行。 從 SQL Server 2017 (14.x)開始,叢集數據行存放區索引可以包含非保存的計算數據行。 不過,在 SQL Server 2017 (14.x), 叢集數據行存放區索引不能包含保存的計算數據行,而且您無法在計算數據行上建立非叢集索引。
  • 頁面和數據列壓縮,以及 vardecimal 記憶體格式。 (資料行存放區索引已經以不同的格式壓縮。
  • 使用叢集數據行存放區索引進行複寫。 支援非叢集數據行存放區索引。 如需詳細資訊,請參閱 sp_addarticle
  • Filestream.

您無法在具有叢集資料行存放區索引的數據表上使用資料指標或觸發程式。 這項限制不適用於非叢集數據行存放區索引。 您可以在具有非叢集數據行存放區索引的數據表上使用數據指標和觸發程式。

SQL Server 2014 (12.x) 特定限制:

下列限制僅適用於 SQL Server 2014 (12.x)。 在此版本中,您可以使用可更新的叢集數據行存放區索引。 非叢集數據行存放區索引仍然是唯讀的。

  • 變更追蹤。 您無法搭配資料行存放區索引使用變更追蹤。
  • 異動數據擷取。 無法在具有叢集數據行存放區索引的數據表上啟用此功能。 從 SQL Server 2016 (13.x)開始,變更數據擷取可以在具有非叢集數據行存放區索引的數據表上啟用。
  • 可讀的次要。 您無法從 Always On 可讀取可用性群組的可讀取次要資料庫存取叢集資料行存放區索引 (CCI)。 您可以從可讀取的次要資料庫存取非叢集數據行存放區索引 (NCCI)。
  • 多個作用中結果集 (MARS)。 SQL Server 2014 (12.x) 會使用這項功能對具有數據行存放區索引之數據表的唯讀連線。 不過,SQL Server 2014 (12.x) 不支援具有數據行存放區索引之數據表上的並行數據作語言 (DML) 作業此功能。 如果您嘗試針對此功能使用此功能,SQL Server 會終止連線並取消交易。
  • 無法在檢視或索引檢視上建立非叢集數據行存放區索引。

如需資料行存放區索引效能優勢和限制的相關資訊,請參閱 資料行存放區索引:概觀

Metadata

欄存索引中的所有資料行都會在中繼資料中儲存為內含欄位。 列存儲索引並不包含鍵欄位。 下列系統檢視提供資料行存放區索引的相關信息:

範例:將數據表從數據列存放區轉換成數據行存放區

A. 將堆積轉換成叢集數據行存放區索引

此範例會將數據表建立為堆積,然後將它轉換成名為 cci_Simple的叢集數據行存放區索引。 建立叢集數據行存放區索引會將整個數據表的記憶體從數據列存放區變更為數據行存放區。

CREATE TABLE dbo.SimpleTable
(
    ProductKey INT NOT NULL,
    OrderDateKey INT NOT NULL,
    DueDateKey INT NOT NULL,
    ShipDateKey INT NOT NULL
);
GO

CREATE CLUSTERED COLUMNSTORE INDEX cci_Simple
    ON dbo.SimpleTable;
GO

B. 將叢集索引轉換為具有相同名稱的叢集數據行存放區索引

此範例會建立具有叢集索引的數據表,然後示範將叢集索引轉換成叢集數據行存放區索引的語法。 建立叢集數據行存放區索引會將整個數據表的記憶體從數據列存放區變更為數據行存放區。

CREATE TABLE dbo.SimpleTable2
(
    ProductKey INT NOT NULL,
    OrderDateKey INT NOT NULL,
    DueDateKey INT NOT NULL,
    ShipDateKey INT NOT NULL
);
GO

CREATE CLUSTERED INDEX cl_simple
    ON dbo.SimpleTable2(ProductKey);
GO

CREATE CLUSTERED COLUMNSTORE INDEX cl_simple
    ON dbo.SimpleTable2 WITH (DROP_EXISTING = ON);
GO

C. 將資料列存放區數據表轉換成數據行存放區索引時,處理非叢集索引

此範例示範當您將數據列存放區數據表轉換成數據行存放區索引時,如何處理非叢集索引。 從 SQL Server 2016 (13.x) 開始,不需要採取任何特殊動作。 SQL Server 會自動定義並重建新叢集數據行存放區索引上的非叢集索引。

如果您想要卸除非叢集索引,請先使用DROP INDEX語句,再建立資料行存放區索引。 DROP EXISTING 選項只會卸除正在轉換的叢集索引。 它不會卸除非叢集索引。

在 SQL Server 2012 (11.x) 和 SQL Server 2014 (12.x), 您無法在資料行存放區索引上建立非叢集索引。

--Create the table for use with this example.
CREATE TABLE dbo.SimpleTable
(
    ProductKey INT NOT NULL,
    OrderDateKey INT NOT NULL,
    DueDateKey INT NOT NULL,
    ShipDateKey INT NOT NULL
);
GO

--Create two nonclustered indexes for use with this example
CREATE INDEX nc1_simple ON dbo.SimpleTable(OrderDateKey);
CREATE INDEX nc2_simple ON dbo.SimpleTable(DueDateKey);
GO

只有 SQL Server 2012 (11.x) 和 SQL Server 2014 (12.x),您才能卸除非叢集索引,才能建立數據行存放區索引。

DROP INDEX dbo.SimpleTable.nc1_simple;
DROP INDEX dbo.SimpleTable.nc2_simple;

--Convert the rowstore table to a columnstore index.
CREATE CLUSTERED COLUMNSTORE INDEX cci_simple
    ON dbo.SimpleTable;
GO

D. 將大型事實數據表從數據列存放區轉換成數據行存放區

此範例說明如何將大型事實數據表從數據列存放區數據表轉換成數據行存放區數據表。

  1. 在此範例中建立要使用的小型數據表。

    --Create a rowstore table with a clustered index and a nonclustered index.
    CREATE TABLE dbo.MyFactTable
    (
        ProductKey INT NOT NULL,
        OrderDateKey INT NOT NULL,
        DueDateKey INT NOT NULL,
        ShipDateKey INT NOT NULL INDEX IDX_CL_MyFactTable CLUSTERED (ProductKey)
    );
    
    --Add a nonclustered index.
    CREATE INDEX my_index
        ON dbo.MyFactTable(ProductKey, OrderDateKey);
    
  2. 從數據列存放區數據表卸除所有非叢集索引。 您可能想要 編寫索引的腳本,以便稍後重新建立索引

    --Drop all nonclustered indexes
    DROP INDEX my_index
        ON dbo.MyFactTable;
    
  3. 將數據列存放區數據表轉換成具有叢集數據行存放區索引的數據行存放區數據表。

    首先,查閱現有叢集數據列存放區索引的名稱。 在步驟 1 中,我們將索引的名稱設定為 IDX_CL_MyFactTable。 如果未指定索引名稱,就會獲得自動產生的唯一索引名稱。 您可以使用下列範例查詢來擷取自動產生的名稱:

    SELECT i.object_id,
           i.name,
           t.object_id,
           t.name
    FROM sys.indexes AS i
         INNER JOIN sys.tables AS t
             ON i.object_id = t.object_id
    WHERE i.type_desc = 'CLUSTERED'
          AND t.name = 'MyFactTable';
    

    選項 1:卸除現有的叢集索引 IDX_CL_MyFactTable,並轉換成 MyFactTable 數據行存放區。 變更新叢集數據行存放區索引的名稱。

    --Drop the clustered rowstore index.
    DROP INDEX [IDX_CL_MyFactTable]
        ON dbo.MyFactTable;
    GO
    
    --Create a new clustered columnstore index with the name MyCCI.
    CREATE CLUSTERED COLUMNSTORE INDEX IDX_CCL_MyFactTable
        ON dbo.MyFactTable;
    GO
    

    選項 2:轉換成資料行存放區,並重複使用現有的數據列存放區叢集索引名稱。

    --Create the clustered columnstore index,
    --replacing the existing rowstore clustered index of the same name
    CREATE CLUSTERED COLUMNSTORE INDEX [IDX_CL_MyFactTable]
        ON dbo.MyFactTable WITH (DROP_EXISTING = ON);
    

E. 將數據行存放區數據表轉換成具有叢集索引的數據列存放區數據表

若要將數據行存放區數據表轉換成具有叢集索引的數據列存放區數據表,請使用 CREATE INDEX 語句搭配 DROP_EXISTING 選項。

CREATE CLUSTERED INDEX [IDX_CL_MyFactTable]
    ON dbo.[MyFactTable](ProductKey) WITH (DROP_EXISTING = ON);

F. 將資料行存放區數據表轉換成數據列存放區堆積

若要將數據行存放區數據表轉換成數據列存放區堆積,請卸除叢集數據行存放區索引。 這通常不建議使用,但有些用途有限。 如需堆積的詳細資訊,請參閱堆積(不含叢集索引的數據表)。

DROP INDEX [IDX_CL_MyFactTable]
    ON dbo.[MyFactTable];

G. 重新組織數據行存放區索引來重組

有兩種方式可維護叢集數據行存放區索引。 從 SQL Server 2016 (13.x) 開始,請使用 ALTER INDEX...REORGANIZE 而不是 REBUILD。 如需詳細資訊,請參閱 數據行存放區索引數據列群組。 在舊版 SQL Server 中,您可以搭配 DROP_EXISTING=ON 或 ALTER INDEX 和 REBUILD 選項使用 CREATE CLUSTERED COLUMNSTORE INDEX。 這兩種方法都取得了相同的結果。

首先,在 中 MyFactTable判斷叢集數據行存放區索引名稱。

SELECT i.object_id,
       i.name,
       t.object_id,
       t.name
FROM sys.indexes AS i
     INNER JOIN sys.tables AS t
         ON i.object_id = t.object_id
WHERE i.type_desc = 'CLUSTERED COLUMNSTORE'
      AND t.name = 'MyFactTable';

在數據行存放區索引上執行 REORGANIZE,以移除片段。

--Rebuild the entire index by using ALTER INDEX and the REBUILD option.
ALTER INDEX IDX_CL_MyFactTable
    ON dbo.[MyFactTable] REORGANIZE;

非叢集數據行存放區索引的範例

A. 在數據列存放區數據表上建立數據行存放區索引作為次要索引

此範例會在數據列存放區數據表上建立非叢集數據行存放區索引。 在此情況下,只能建立一個數據行存放區索引。 數據行存放區索引需要額外的記憶體,因為它包含數據列存放區數據表中的數據複本。 此範例會建立簡單的數據表和數據列存放區叢集索引,然後示範建立非叢集數據行存放區索引的語法。

CREATE TABLE dbo.SimpleTable
(
    ProductKey INT NOT NULL,
    OrderDateKey INT NOT NULL,
    DueDateKey INT NOT NULL,
    ShipDateKey INT NOT NULL
);
GO

CREATE CLUSTERED INDEX cl_simple
    ON dbo.SimpleTable(ProductKey);
GO

CREATE NONCLUSTERED COLUMNSTORE INDEX csindx_simple
    ON dbo.SimpleTable(OrderDateKey, DueDateKey, ShipDateKey);
GO

B. 使用所有選項建立基本非叢集數據行存放區索引

下列範例示範在 DEFAULT 檔案群組上建立非叢集數據行存放區索引的語法,並將平行處理原則的最大程度指定為 2。

CREATE NONCLUSTERED COLUMNSTORE INDEX csindx_simple
    ON SimpleTable(OrderDateKey, DueDateKey, ShipDateKey) WITH (DROP_EXISTING = ON, MAXDOP = 2)
    ON "DEFAULT";
GO

C. 使用篩選述詞建立非叢集數據行存放區索引

下列範例會在範例資料庫中的Production.BillOfMaterials數據表上AdventureWorks2025建立篩選的非叢集數據行存放區索引。 篩選述詞可以包含不是已篩選索引中索引鍵數據行的數據行。 此範例中的述詞只會選取非 NULL 的數據 EndDate 列。

IF EXISTS (SELECT name
           FROM sys.indexes
           WHERE name = N'FIBillOfMaterialsWithEndDate'
                 AND object_id = OBJECT_ID(N'Production.BillOfMaterials'))
    DROP INDEX FIBillOfMaterialsWithEndDate
        ON Production.BillOfMaterials;
GO

CREATE NONCLUSTERED COLUMNSTORE INDEX "FIBillOfMaterialsWithEndDate"
    ON Production.BillOfMaterials(ComponentID, StartDate)
    WHERE EndDate IS NOT NULL;

D. 變更非叢集數據行存放區索引中的數據

適用於:SQL Server 2012 (11.x) 到 SQL Server 2014 (12.x)。

在 SQL Server 2014 (12.x) 和舊版中,在數據表上建立非叢集數據行存放區索引之後,您無法直接修改該數據表中的數據。 INSERT、UPDATE、DELETE 或 MERGE 的查詢失敗,並傳回錯誤訊息。 以下是可用來新增或修改資料表中數據的選項:

  • 停用或卸除數據行存放區索引。 然後,您可以更新資料表中的數據。 如果您停用資料行存放區索引,您可以在完成更新數據時重建數據行存放區索引。 例如:

    ALTER INDEX mycolumnstoreindex
        ON dbo.mytable DISABLE;
    
    -- update the data in mytable as necessary
    ALTER INDEX mycolumnstoreindex
        ON dbo.mytable REBUILD;
    
  • 將數據載入沒有資料行存放區索引的臨時表。 在暫存表上建置列存儲索引。 將臨時表移入主資料表的空白分割區。

  • 將具有列存儲索引的數據表中的某個分割區切換到空的暫存表。 如果預備資料表上有資料行存放區索引,請停用資料行存放區索引。 執行任何更新。 建置 (或重建) 資料行存放區索引。 將階段表切換回主表中(現在是空的)的分區。

範例:Azure Synapse Analytics、Analytics Platform System (PDW)

A. 將叢集索引變更為叢集數據行存放區索引

使用 CREATE CLUSTERED COLUMNSTORE INDEX 語句搭配 DROP_EXISTING = ON,您可以:

  • 將叢集索引變更為叢集數據行存放區索引。

  • 重建叢集數據行存放區索引。

此範例會將 xDimProduct 數據表建立為具有叢集索引的數據列存放區數據表。 然後,此範例會使用 CREATE CLUSTERED COLUMNSTORE INDEX,將數據表從數據列存放區數據表變更為數據行存放區數據表。

-- Uses AdventureWorks
IF EXISTS (SELECT name
           FROM sys.tables
           WHERE name = N'xDimProduct'
                 AND object_id = OBJECT_ID(N'xDimProduct'))
    DROP TABLE xDimProduct;

--Create a distributed table with a clustered index.
CREATE TABLE xDimProduct
(
    ProductKey,
    ProductAlternateKey,
    ProductSubcategoryKey
)
WITH (DISTRIBUTION = HASH(ProductKey), CLUSTERED INDEX(ProductKey)) AS
SELECT ProductKey,
       ProductAlternateKey,
       ProductSubcategoryKey
FROM DimProduct;

使用 sys.indexes查詢系統元數據中針對新數據表自動建立的叢集索引名稱。 例如:

SELECT i.object_id,
       i.name,
       t.object_id,
       t.name,
       i.type_desc
FROM sys.indexes AS i
     INNER JOIN sys.tables AS t
         ON i.object_id = t.object_id
WHERE i.type_desc = 'CLUSTERED'
      AND t.name = 'xdimProduct';

現在,您可以選擇:

  1. 卸除具有自動建立名稱的現有叢集數據行存放區索引,然後使用使用者定義的名稱建立新的叢集數據行存放區索引。
  2. 卸除現有索引,並將現有的索引取代為叢集資料行存放區索引,並保留相同的系統產生名稱,例如 ClusteredIndex_1bd8af8797f7453182903cc68df48541

例如:

--1. DROP the existing clustered columnstore index with an automatically-created name, for example:
DROP INDEX ClusteredIndex_1bd8af8797f7453182903cc68df48541
    ON xdimProduct;
GO

CREATE CLUSTERED COLUMNSTORE INDEX [<new_index_name>]
    ON xdimProduct;
GO

--Or,
--2. Change the existing clustered index to a clustered columnstore index with the same name.
CREATE CLUSTERED COLUMNSTORE INDEX [ClusteredIndex_1bd8af8797f7453182903cc68df48541]
    ON xdimProduct WITH (DROP_EXISTING = ON);
GO

B. 重建叢集數據行存放區索引

此範例會使用 CREATE CLUSTERED COLUMNSTORE INDEX 來重建現有的叢集資料行存放區索引,稱為 cci_xDimProduct

--Rebuild the existing clustered columnstore index.
CREATE CLUSTERED COLUMNSTORE INDEX cci_xDimProduct
    ON xdimProduct WITH (DROP_EXISTING = ON);

C. 變更叢集數據行存放區索引的名稱

若要變更叢集數據行存放區索引的名稱,請卸除現有的叢集數據行存放區索引,然後使用新的名稱重新建立索引。

建議您將此作業限制為小型或空白資料表。 卸除大型叢集數據行存放區索引並使用不同的名稱重建需要很長的時間。

此範例會參考上一個範例中的 cci_xDimProduct 叢集數據行存放區索引。 此範例會卸除叢集數據 cci_xDimProduct 行存放區索引,然後使用 名稱 mycci_xDimProduct重新建立叢集數據行存放區索引。

--For illustration purposes, drop the clustered columnstore index.
--The table continues to be distributed, but changes to a heap.
DROP INDEX cci_xdimProduct
    ON xDimProduct;

--Create a clustered index with a new name, mycci_xDimProduct.
CREATE CLUSTERED COLUMNSTORE INDEX mycci_xDimProduct
    ON xdimProduct WITH (DROP_EXISTING = OFF);

D. 將數據行存放區數據表轉換成具有叢集索引的數據列存放區數據表

您可能想要卸除叢集數據行存放區索引,並建立叢集索引。 當您卸除叢集數據行存放區索引時,數據表會變更為數據列存放區格式。 本範例會將數據行存放區數據表轉換成具有相同名稱的叢集索引的數據列存放區數據表。 不會遺失任何數據。 所有數據都會移至數據列存放區數據表,而列出的數據行會成為叢集索引中的索引鍵數據行。

--Drop the clustered columnstore index and create a clustered rowstore index.
--All of the columns are stored in the rowstore clustered index.
--The columns listed are the included columns in the index.
CREATE CLUSTERED INDEX cci_xDimProduct
    ON xdimProduct(ProductKey, ProductAlternateKey, ProductSubcategoryKey, WeightUnitMeasureCode) WITH (DROP_EXISTING = ON);

E. 將資料行存放區數據表轉換回數據列存放區堆積

使用 DROP INDEX 卸除叢集資料行存放區索引,並將資料表轉換成數據列存放區堆積。 這個範例會將 cci_xDimProduct 數據表轉換成數據列存放區堆積。 數據表會繼續散發,但會儲存為堆積。

--Drop the clustered columnstore index. The table continues to be distributed, but changes to a heap.
DROP INDEX cci_xdimProduct
    ON xdimProduct;

F. 在不含索引的數據表上建立已排序的叢集數據行存放區索引

未排序的數據行存放區索引預設涵蓋所有數據行,而不需要指定數據行清單。 已排序的數據行存放區索引可讓您指定資料行的順序。 清單不需要包含所有數據行。

如需詳細資訊,請參閱使用已排序的數據行存放區索引 效能微調

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines ORDER(SHIPDATE);

G. 將叢集資料行存放區索引轉換為已排序的叢集數據行存放區索引

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines ORDER(SHIPDATE) WITH (DROP_EXISTING = ON);

H. 將數據行新增至已排序叢集數據行存放區索引的排序

您可以指定資料列存放區索引中資料行的順序。 原始排序的叢集數據行存放區索引只會在數據行上 SHIPDATE 排序。 下列範例會將數據 PRODUCTKEY 行加入排序中。 如需了解有序的資料行存放庫索引的可用性,請參閱 資料行存放庫索引:概觀

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines ORDER(SHIPDATE, PRODUCTKEY) WITH (DROP_EXISTING = ON);

I. 變更已排序數據行的序數

原始排序的叢集資料行存放區索引是在 上SHIPDATEPRODUCTKEY排序。 下列範例會將排序變更為 PRODUCTKEYSHIPDATE。 如需了解有序的資料行存放庫索引的可用性,請參閱 資料行存放庫索引:概觀

CREATE CLUSTERED COLUMNSTORE INDEX cci
    ON Sales.OrderLines ORDER(PRODUCTKEY, SHIPDATE) WITH (DROP_EXISTING = ON);

J. 建立已排序的叢集數據行存放區索引

您可以使用排序索引鍵建立叢集資料行存放區索引。 建立已排序的叢集數據行存放區索引時,您應該套用查詢提示 MAXDOP = 1 ,以取得排序品質上限和最短持續時間。 如需了解有序的資料行存放庫索引的可用性,請參閱 資料行存放庫索引:概觀

CREATE CLUSTERED COLUMNSTORE INDEX [OrderedCCI]
    ON dbo.FactResellerSalesPartCategoryFull ORDER(EnglishProductSubcategoryName, EnglishProductName) WITH (MAXDOP = 1, DROP_EXISTING = ON);