我最近听到了这样的建议:“如果您使用的是 DISTINCT,我会挑战您修复您的代码。” 但是,我想知道这个建议背后的考虑因素,以及这是否意味着我应该以不同的方式处理以下问题。
问题背景
我有一个非规范化的日期维度表(Kimball 星型架构)。在这张表中,我折叠了几个第三范式表:日期、绝对周、绝对月和年。对于这些折叠表中的每一个,我都有一个表示唯一标识的列、一个文本名称列和一个数字手动排序索引。这是显示结构的示例行,数字仅用于说明(为便于阅读采用垂直形式):
为了便于理解,我选择使用日期维度表,但该问题可以转换为任何其他涉及层次结构的维度表。
问题概要
我想用相关的文本字段检索一组不同的周和月组合。
可能的解决方案
1. 与众不同
SELECT DISTINCT MonthId, WeekId, YearName, MonthName, WeekName
FROM DimDate
Run Code Online (Sandbox Code Playgroud)
请注意,我不能排除 MonthId 或 WeekId,因为我不能假设自由文本字段是唯一的。
2. 分组依据
SELECT MIN(YearName), MIN(MonthName), MIN(WeekName)
FROM DimDate
GROUP BY MonthId, WeekId
Run Code Online (Sandbox Code Playgroud)
3. 行号
WITH grp AS (
SELECT YearName, MonthName, WeekName
, ROW_NUMBER() OVER (PARTITION BY MonthId, WeekId) AS r
FROM DimDate
)
SELECT YearName, MonthName, WeekName
FROM grp
WHERE grp.r = 1
Run Code Online (Sandbox Code Playgroud)
4.ETL
在这种方法中,非叶属性的每个组合的索引视图都被预先计算并直接查询。显然,这在查询时是最快的,但可能需要多次复制维度表,具体取决于维度中层次结构的复杂性。
注释
我希望该ROW_NUMBER解决方案是最快的(不包括ETL方法),但它还需要查询规范中的子查询或 CTE。虽然这不是一个严重的问题,但它确实使查询更难阅读。我希望GROUP BY和DISTINCT方法几乎是等效的,因为每个列都必须以某种形式的排序操作使用,而ROW_NUMBER解决方案只需要对分区列进行排序。
我错过了什么吗?SQL Server 能否更有效地使用非规范化列标识的非唯一索引?
--edit - 附加说明:
周和月标识符是绝对的,因此在此方案中它们表示年份。我强制要求周仅在一年中。在 SSAS 中,将有两个层次结构:日期、周、年和日期、月、年。
我相信 DISTINCT 给出了相同的输出,因为请求的列仅因周、月或年而异,而周和月都暗示了年。
索引目前仅在标识符列上(单列非唯一)
通常,我正在对事实表执行聚合查询,但通过一组由最终用户选择且事先未知的非叶维度属性进行报告。我试图减少这个问题的问题空间。
根据我的经验,聚合(DISTINCT 或 GROUP BY)可能比 ROW_NUMBER() 方法更快。也就是说,SQL Server 2008 的 ROW_NUMBER 比 SQL Server 2005 更好。
不过,你还是得根据自己的情况去尝试一下。
比较查询计划,并使用Profiler和SET捕获IO、CPU、Duration等
有关大量背景信息,请参阅以下问题:
最后,您是否需要 ROW_NUMBER 方法?看起来您正在解决由非规范化引起的问题。
还有一些注意事项:
| 归档时间: |
|
| 查看次数: |
16163 次 |
| 最近记录: |