列存储索引不触发star join,其加速依赖压缩、行组消除和向量化执行;事实表需按维度键排序(如用maxdop=1重建)以启用行组消除,且维度表须有主键/唯一约束并更新统计信息。

列存索引本身不触发Star Join,别指望自动优化
SQL Server 没有 Oracle 那套 STAR_TRANSFORMATION_ENABLED 机制,也不会因为建了列存索引就自动走星型转换路径。它的加速逻辑完全不同:靠压缩、靠行组消除、靠向量化执行,而不是靠重写 JOIN 顺序。你建了 CLUSTERED COLUMNSTORE INDEX,但执行计划里仍出现 Hash Match 或 Nested Loops,这完全正常——不是失败,是预期行为。
事实表必须按维度键排序,否则行组消除失效
列存索引不维护物理顺序,但行组消除(Rowgroup Elimination)依赖数据局部性。如果事实表按时间插入,而常用过滤条件是 WHERE customer_id = 123,那这个谓词大概率无法跳过行组,全表扫描照旧。
- 先在事实表上建行存储聚集索引,按主维度键(如
customer_id或product_id)排序 - 再用
CREATE CLUSTERED COLUMNSTORE INDEX ... WITH (DROP_EXISTING = ON, MAXDOP = 1)转换——MAXDOP = 1是关键,它让最终列存行组严格按聚集索引顺序填充 - 验证是否生效:查
sys.dm_db_column_store_row_group_physical_stats,看min_data_id/max_data_id是否在各维度值区间内紧凑分布
JOIN 性能卡在驱动表选择?检查兼容性级别和统计信息
SQL Server 2016 默认兼容级别是 130,但如果你从旧版本升级或显式设为 120/110,新基数估算器(CE)不会启用,可能导致优化器低估维度表返回行数,错误把大事实表当驱动表。
- 确认当前设置:
SELECT compatibility_level FROM sys.databases WHERE name = 'YourDW' - 若低于 130,建议升到 130;不要盲目升到 150(那是 2019 的),CE v150 在星型查询中反而更容易误判
- 维度表必须有
PRIMARY KEY或UNIQUE约束,且统计信息要新鲜:对小维度表执行UPDATE STATISTICS dim_customer WITH FULLSCAN,避免采样失真 - 事实表统计信息可采样更新:
UPDATE STATISTICS fact_sales WITH SAMPLE 20 PERCENT,太全反而拖慢维护
别忽略分区和物化路径,这是真正降延迟的杠杆
单靠列存索引 + 手动排序,只能解决“扫得少”,不能解决“算得快”。星型模型下高频聚合(如 SUM(sales_amt) GROUP BY cust_state)仍需大量运行时计算。
- 对事实表按时间字段(如
sale_date)做范围分区,配合SWITCH快速归档旧数据,避免扫描无用分区 - 用
MATERIALIZED VIEW(SQL Server 2022+)或等价手段(如定期刷新汇总表)预计算常用fact JOIN dim路径,比调优单条 SQL 有效得多 - 如果还在用 2016,考虑用
INDEXED VIEW模拟物化效果,但注意:必须用SCHEMABINDING+UNIQUE CLUSTERED INDEX,且 JOIN 条件不能含函数或隐式转换
最常被跳过的点是:以为建了列存索引就一劳永逸,却没碰过事实表的插入顺序、没验证过行组分布、也没管维度表约束是否真实存在。这些细节不处理,再大的内存和再多的 CPU 也救不了 JOIN 延迟。










