Skip to content

Commit b84cf34

Browse files
authored
Merge pull request #36223 from dimitri-furman/dfurman/ordered-columnstore
Add a columnstore order quality sample link
2 parents c13a12d + d3a3dd2 commit b84cf34

2 files changed

Lines changed: 42 additions & 38 deletions

File tree

docs/relational-databases/indexes/ordered-columnstore-indexes.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: "Learn more about how ordered columnstore indexes can benefit query
44
author: WilliamDAssafMSFT
55
ms.author: wiassaf
66
ms.reviewer: nibruno, xiaoyul, randolphwest, dfurman
7-
ms.date: 01/06/2026
7+
ms.date: 01/12/2026
88
ms.service: sql
99
ms.subservice: performance
1010
ms.topic: article
@@ -39,7 +39,7 @@ When you create an ordered columnstore index by specifying the `ORDER` clause in
3939

4040
## Reduce segment overlap and improve query performance
4141

42-
When you build an ordered columnstore index, the [!INCLUDE [ssDE](../../includes/ssde-md.md)] sorts the data on a best-effort basis. Depending on the available memory, the data size, the degree of parallelism, the index type (clustered vs. nonclustered), and the type of index build (offline vs. online), the order a column in a columnstore index might be full with no segment overlap, or partial with some segment overlap. When there are fewer overlapping segments, a query that can take advantage of column order runs faster.
42+
When you build an ordered columnstore index, the [!INCLUDE [ssDE](../../includes/ssde-md.md)] sorts the data on a best-effort basis. Depending on the available memory, the data size, the degree of parallelism, the index type (clustered vs. nonclustered), and the type of index build (offline vs. online), the order in a column in a columnstore index might be full with no segment overlap, or partial with some segment overlap. When there are fewer overlapping segments, a query that can take advantage of column order runs faster.
4343

4444
> [!TIP]
4545
> Even if the order in a column of a columnstore index is partial, segments can still be eliminated (skipped). A full order isn't required to gain performance benefits if a partial order avoids many segment overlaps.
@@ -62,6 +62,8 @@ You can create or rebuild ordered columnstore indexes online only in some SQL pl
6262

6363
In SQL Server, online index operations aren't available in all editions. For more information, see [Editions and supported features of SQL Server 2025](../../sql-server/editions-and-components-of-sql-server-2025.md) and [Perform index operations online](perform-index-operations-online.md).
6464

65+
For certain data types and encodings, the [sys.column_store_segments](../system-catalog-views/sys-column-store-segments-transact-sql.md) system view can help you find the number of segment overlaps. A [sample script](https://github.com/microsoft/sql-server-samples/blob/master/samples/features/columnstore/ordered-columnstore/order-quality.sql) based on this view determines the order quality for eligible columns of all columnstore indexes in the current database.
66+
6567
## Query performance
6668

6769
The performance gain from an ordered columnstore index depends on the query patterns, the size of data, the number of overlapping segments, and the compute resources available for query execution.

docs/relational-databases/system-catalog-views/sys-column-store-segments-transact-sql.md

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "sys.column_store_segments (Transact-SQL)"
33
description: "sys.column_store_segments returns one row for each column segment in a columnstore index. There is one column segment per column per rowgroup."
44
author: rwestMSFT
55
ms.author: randolphwest
6-
ms.date: 10/14/2022
6+
ms.date: 1/12/2026
77
ms.service: sql
88
ms.subservice: system-objects
99
ms.topic: "reference"
@@ -17,44 +17,46 @@ helpviewer_keywords:
1717
dev_langs:
1818
- "TSQL"
1919
---
20+
2021
# sys.column_store_segments (Transact-SQL)
21-
[!INCLUDE[SQL Server 2012 Azure SQL Managed Instance](../../includes/applies-to-version/sqlserver2012-asdbmi.md)]
22-
23-
Returns one row for each column segment in a columnstore index. There is one column segment per column per rowgroup. For example, a table with 10 rowgroups and 34 columns returns 340 rows.
24-
25-
|Column name|Data type|Description|
26-
|-----------------|---------------|-----------------|
27-
|**partition_id**|**bigint**|Indicates the partition ID. Is unique within a database.|
28-
|**hobt_id**|**bigint**|ID of the heap or B-tree index (HoBT) for the table that has this columnstore index.|
29-
|**column_id**|**int**|ID of the columnstore column.|
30-
|**segment_id**|**int**|ID of the rowgroup. For backward compatibility, the column name continues to be called segment_id even though this is the rowgroup ID. You can uniquely identify a segment using \<hobt_id, partition_id, column_id>, <segment_id>.|
31-
|**version**|**int**|Version of the column segment format.|
32-
|**encoding_type**|**int**|Type of encoding used for that segment:<br /><br />1 = VALUE_BASED - non-string/binary with no dictionary (similar to 4 with some internal variations)<br /><br />2 = VALUE_HASH_BASED - non-string/binary column with common values in dictionary<br /><br />3 = STRING_HASH_BASED - string/binary column with common values in dictionary<br /><br />4 = STORE_BY_VALUE_BASED - non-string/binary with no dictionary<br /><br />5 = STRING_STORE_BY_VALUE_BASED - string/binary with no dictionary<br /><br />For more information, see the [Remarks](#remarks) section.|
33-
|**row_count**|**int**|Number of rows in the row group.|
34-
|**has_nulls**|**int**|1 if the column segment has null values.|
35-
|**base_id**|**bigint**|Base value ID if encoding type 1 is being used. If encoding type 1 is not being used, base_id is set to -1.|
36-
|**magnitude**|**float**|Magnitude if encoding type 1 is being used. If encoding type 1 is not being used, magnitude is set to -1.|
37-
|**primary_dictionary_id**|**int**|A value of 0 represents the global dictionary. A value of -1 indicates that there is no global dictionary created for this column.|
38-
|**secondary_dictionary_id**|**int**|A non-zero value points to the local dictionary for this column in the current segment (for example, the rowgroup). A value of -1 indicates that there is no local dictionary for this segment.|
39-
|**min_data_id**|**bigint**|Minimum data ID in the column segment.|
40-
|**max_data_id**|**bigint**|Maximum data ID in the column segment.|
41-
|**null_value**|**bigint**|Value used to represent nulls.|
42-
|**on_disk_size**|**bigint**|Size of segment in bytes.|
43-
|**collation_id**|**int** |**Applies to [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)]** and later.<br />Current collation when the segment was created. Maps to an internal ID. **Currently internal only and not for development.** |
44-
|**min_deep_data**|**varbinary(18)**| **Applies to [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)]** and later.<br />Used for segment elimination.<sup>1</sup> For internal use only. |
45-
|**max_deep_data** |**varbinary(18)**| **Applies to [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)]** and later.<br />Used for segment elimination.<sup>1</sup> For internal use only. |
46-
47-
<sup>1</sup> After upgrading to a version of SQL Server that supports string min/max segment elimination ([!INCLUDE[sssql22-md](../../includes/sssql22-md.md)] and later), `min_deep_data` and `max_deep_data` will be `NULL` until after the columnstore index is rebuilt, using a REBUILD or DROP/CREATE. After a rebuild, the segments that contain data types that can benefit from string min/max segment elimination will contain data.
22+
23+
[!INCLUDE [sql-asdb-asdbmi-fabricsqldb](../../includes/applies-to-version/sql-asdb-asdbmi-fabricsqldb.md)]
24+
25+
Returns one row for each column segment in a columnstore index. There is one column segment per column per rowgroup. For example, a columnstore index with 10 rowgroups and 34 columns has 340 rows in this view.
26+
27+
| Column name | Data type | Description |
28+
| --- | --- | --- |
29+
| `partition_id` | **bigint** | Indicates the partition ID. Is unique within a database. |
30+
| `hobt_id` | **bigint** | ID of the heap or B-tree index (HoBT) for the table that has this columnstore index. |
31+
| `column_id` | **int** | ID of the columnstore column. |
32+
| `segment_id` | **int** | ID of the rowgroup. For backward compatibility, the column name continues to be called segment_id even though this is the rowgroup ID. You can uniquely identify a segment using `<hobt_id, partition_id, column_id, segment_id>`. |
33+
| `version` | **int** | Version of the column segment format. |
34+
| `encoding_type` | **int** | Type of encoding used for that segment:<br /><br />1 = VALUE_BASED - non-string/binary with no dictionary (similar to 4 with some internal variations)<br /><br />2 = VALUE_HASH_BASED - non-string/binary column with common values in dictionary<br /><br />3 = STRING_HASH_BASED - string/binary column with common values in dictionary<br /><br />4 = STORE_BY_VALUE_BASED - non-string/binary with no dictionary<br /><br />5 = STRING_STORE_BY_VALUE_BASED - string/binary with no dictionary<br /><br />For more information, see the [Remarks](#remarks) section. |
35+
| `row_count` | **int** | Number of rows in the row group. |
36+
| `has_nulls` | **int** | 1 if the column segment has NULLs. |
37+
| `base_id` | **bigint** | Base value ID if encoding type 1 is being used. If encoding type 1 is not being used, `base_id` is set to -1. |
38+
| `magnitude` | **float** | Magnitude if encoding type 1 is being used. If encoding type 1 is not being used, `magnitude` is set to -1. |
39+
| `primary_dictionary_id` | **int** | A value of 0 represents the global dictionary. A value of -1 indicates that there is no global dictionary created for this column. |
40+
| `secondary_dictionary_id` | **int** | A non-zero value points to the local dictionary for this column in the current segment (for example, the rowgroup). A value of -1 indicates that there is no local dictionary for this segment. |
41+
| `min_data_id` | **bigint** | For internal use only. |
42+
| `max_data_id` | **bigint** | For internal use only. |
43+
| `null_value` | **bigint** | Value used to represent nulls. |
44+
| `on_disk_size` | **bigint** | Size of segment in bytes. |
45+
| `collation_id` | **int** | Current collation when the segment was created. Maps to an internal ID. For internal use only.<br /><br />**Applies to:** [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)] and later versions, [!INCLUDE [ssazure-sqldb](../../includes/ssazure-sqldb.md)], and [!INCLUDE[ssazuremi-md](../../includes/ssazuremi-md.md)] |
46+
| `min_deep_data` | **varbinary(18)** | Used for segment elimination.<sup>1</sup> For internal use only.<br /><br />**Applies to:** [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)] and later versions, [!INCLUDE [ssazure-sqldb](../../includes/ssazure-sqldb.md)], and [!INCLUDE[ssazuremi-md](../../includes/ssazuremi-md.md)] |
47+
| `max_deep_data` | **varbinary(18)** | Used for segment elimination.<sup>1</sup> For internal use only.<br /><br />**Applies to:** [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)] and later versions, [!INCLUDE [ssazure-sqldb](../../includes/ssazure-sqldb.md)], and [!INCLUDE[ssazuremi-md](../../includes/ssazuremi-md.md)] |
48+
49+
<sup>1</sup> After upgrading to a version of the [!INCLUDE [ssde-md](../../includes/ssde-md.md)] that supports min/max segment elimination for an expanded set of data types (introduced in [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)]), the `min_deep_data` and `max_deep_data` are `NULL` until the columnstore index is rebuilt using an `ALTER INDEX ... REBUILD` or `CREATE INDEX ... WITH (DROP_EXISTING = ON)` statement.
4850

4951
## Remarks
5052

51-
The columnstore segment encoding type is selected by the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] with the goal of achieving the lowest storage cost, by analyzing the segment data. If data is mostly distinct, the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] uses value-based encoding. If data is mostly not distinct, the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] uses hash-based encoding. The choice between string-based and value-based encoding is related to the type of data being stored, whether string data or binary data. All encodings take advantage of bit-packing and run-length encoding when possible.
53+
The columnstore segment encoding type is selected by the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] by analyzing the segment data with the goal of achieving the lowest storage cost. If data is mostly distinct, the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] uses value-based encoding. If data is mostly not distinct, the [!INCLUDE[ssDE-md](../../includes/ssde-md.md)] uses hash-based encoding. The choice between string-based and value-based encoding is related to the type of data being stored, whether string data or binary data. All encodings take advantage of bit-packing and run-length encoding when possible.
5254

53-
Columnstore segment elimination applies to numeric, date, and time data types, and the datetimeoffset data type with scale less than or equal to two. Beginning in [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)], segment elimination capabilities extend to string, binary, guid data types, and the datetimeoffset data type for scale greater than two. Segment elimination does not apply to LOB data types such as the (max) data type lengths.
55+
Columnstore segment elimination applies to numeric, date, and time data types, and the **datetimeoffset** data type with scale less than or equal to two. Beginning in [!INCLUDE[sssql22-md](../../includes/sssql22-md.md)], segment elimination capabilities expand to string and binary data types, the **uniqueidentifier** data type, and the **datetimeoffset** data type for scale greater than two. Segment elimination does not apply to LOB data types such as **varchar(max)**, **nvarchar(max)**, and **varbinary(max)**. For more information, see [What's new in columnstore indexes](../indexes/columnstore-indexes-what-s-new.md#sql-server-2022-16x).
5456

5557
## Permissions
5658

57-
All columns require at least `VIEW DEFINITION` permission on the table. The following columns return `NULL` unless the user also has `SELECT` permission: `has_nulls`, `base_id`, `magnitude`, `min_data_id`, `max_data_id`, and `null_value`.
59+
The `VIEW DEFINITION` permission on the view is required. The following columns return `NULL` unless the user also has the `SELECT` permission: `has_nulls`, `base_id`, `magnitude`, `min_data_id`, `max_data_id`, and `null_value`.
5860

5961
[!INCLUDE[ssCatViewPerm](../../includes/sscatviewperm-md.md)] For more information, see [Metadata Visibility Configuration](../../relational-databases/security/metadata-visibility-configuration.md).
6062

@@ -71,17 +73,17 @@ INNER JOIN sys.partitions AS p
7173
INNER JOIN sys.indexes AS i
7274
ON p.object_id = i.object_id
7375
WHERE i.type = 5 OR i.type = 6
74-
GROUP BY i.name, p.object_id, p.index_id, i.type_desc ;
75-
GO
76+
GROUP BY i.name, p.object_id, p.index_id, i.type_desc;
7677
```
7778

78-
## Next steps
79+
## Related content
7980

81+
- [Columnstore Indexes Guide](../indexes/columnstore-indexes-overview.md)
82+
- [Performance tuning with ordered columnstore indexes](../indexes/ordered-columnstore-indexes.md)
8083
- [Object Catalog Views (Transact-SQL)](../../relational-databases/system-catalog-views/object-catalog-views-transact-sql.md)
8184
- [Catalog Views (Transact-SQL)](../../relational-databases/system-catalog-views/catalog-views-transact-sql.md)
8285
- [Querying the SQL Server System Catalog FAQ](../../relational-databases/system-catalog-views/querying-the-sql-server-system-catalog-faq.yml)
8386
- [sys.columns (Transact-SQL)](../../relational-databases/system-catalog-views/sys-columns-transact-sql.md)
8487
- [sys.all_columns (Transact-SQL)](../../relational-databases/system-catalog-views/sys-all-columns-transact-sql.md)
8588
- [sys.computed_columns (Transact-SQL)](../../relational-databases/system-catalog-views/sys-computed-columns-transact-sql.md)
86-
- [Columnstore Indexes Guide](~/relational-databases/indexes/columnstore-indexes-overview.md)
87-
- [sys.column_store_dictionaries (Transact-SQL)](../../relational-databases/system-catalog-views/sys-column-store-dictionaries-transact-sql.md)
89+
- [sys.column_store_dictionaries (Transact-SQL)](../../relational-databases/system-catalog-views/sys-column-store-dictionaries-transact-sql.md)

0 commit comments

Comments
 (0)