设计EDW表时,SQL Server能否共存聚集列存储与非聚集索引?
SQL Server中聚集列存储索引与非聚集索引的共存问题
首先直接给你明确结论:你不能在同一张SQL Server表中同时拥有行存储聚集索引和聚集列存储索引——这两者是互斥的,因为它们定义了表数据的核心物理存储方式:行存储聚集索引是把数据按行排序后物理存储,而聚集列存储索引是把数据按列压缩存储,一张表只能选一种作为底层存储结构。
具体规则和可行方案:
- 互斥性限制:如果表已经存在行存储聚集索引,尝试创建聚集列存储索引会直接报错;反过来,如果表已经有聚集列存储索引,也不能再创建行存储聚集索引。典型错误提示类似:
CREATE CLUSTERED COLUMNSTORE INDEX cannot be created on table 'YourTableName' because it already has a clustered index. - 可行的组合:虽然不能同时有行存储聚集索引和聚集列存储索引,但你可以在聚集列存储索引的表上创建多个非聚集行存储索引,这是完全支持的,也是EDW场景中很实用的组合。
EDW场景下的实践建议:
对于企业数据仓库的表设计,这个组合尤其适合事实表(数据量大、以分析查询为主):
- 给事实表创建聚集列存储索引:它的高压缩比能大幅降低存储成本,并且对批量聚合、大范围扫描类的分析查询性能极佳。
- 针对经常用于过滤、点查的列(比如维度键、高频查询的业务字段)创建非聚集行存储索引:这类索引可以加速特定场景的查询,比如快速定位某个客户或某个产品的销售数据,弥补列存储在小范围点查上的性能短板。
示例代码:
-- 创建销售事实表 CREATE TABLE FactSales ( SaleKey INT IDENTITY(1,1) NOT NULL, ProductKey INT NOT NULL, CustomerKey INT NOT NULL, SaleDateKey INT NOT NULL, Quantity INT NOT NULL, Amount DECIMAL(18,2) NOT NULL ); -- 创建聚集列存储索引,定义表的物理存储方式 CREATE CLUSTERED COLUMNSTORE INDEX CCI_FactSales ON FactSales; -- 添加非聚集索引,加速按产品+日期的查询 CREATE NONCLUSTERED INDEX IX_FactSales_ProductDate ON FactSales (ProductKey, SaleDateKey) INCLUDE (Quantity, Amount);
至于维度表,如果数据量不大,行存储聚集索引(比如按主键聚集)+ 非聚集覆盖索引的组合通常就足够;如果维度表数据量也很大(比如千万级以上),同样可以考虑聚集列存储+非聚集索引的方案。
内容的提问来源于stack exchange,提问作者Andres Angel
相关产品推荐
相关产品推荐

