Cardinality 是数据库和数据建模领域的一个重要的基础概念,数据库领域的 Cardinality 表示去重后唯一值(Unique Values)的数量,比如 Columns Cardinality 指列包含的不重复值的个数,数据建模中的 Cardinality 表示关系的类型。
参照微软文档的官方翻译,Cardinality 被译为基数,这个翻译比较抽象,你也可以直接用它的原文。
列基数 Columns Cardinality
列基数是列包含的不重复值的数量。这个数字对于控制列的大小非常重要,它将直接影响模型压缩的效果和引擎扫描时的性能。在允许的范围内,你应该尽量将列基数减少到最低。原因是:
- 基数是影响模型文件大小的关键因素之一,它比我们直觉上认为的行数更重要。
- 许多 DAX 操作(如迭代和筛选)的执行时间直接依赖于这个数字。
列基数与文件大小
我们习惯用行数评估文件的大小,比如认为 100 万行的文件体积比 10 万行的更大,实际上,行数并非决定文件大小的直接因素。DAX 运行在 SQL Server Analysis Services (SSAS)表格模型、Power BI 服务以及作为 Microsoft Excel 插件的 Power Pivot 中,本质上它们都是表格模型的不同形式。
表格模型的数据存储于 VertiPaq,这是一个位于内存中的列式数据库,与行式数据库不同,这是一种以列形式存储数据的结构
VertiPaq 会使用各种手段来压缩数据以减少数据模型的内存占用,包括尝试不同的列编码方式、确定表的最佳排序等等(你将在 Vertipaq 引擎一章详细了解这方面的知识)。在表自身的属性中,列的数据类型、列值的分布特征、列基数都会影响编码效率,进而影响最终的压缩效果,这其中列基数起到关键作用。VertiPaq 为模型的每列创建一个不重复值的字典和一个引用字典的位图索引,这个位图索引可以高度压缩,在某些情况下,高基数列的字典开销可能占该列开销的 90%以上
举例来说,行数相同的列,基数越大,所占的体积也越大,下图是用 PQ 生成的 100 万行随机数的单个列,左表的列基数只有 11,而右表是 1001,需要一张更大的字典表,所以经过压缩后虽然两张表行数相同,但右表的体积更大,是左表的 2.8 倍。
如果在列基数相同的情况下增加行数,这时文件大小取决于数据的分布、压缩算法的效率和引擎的版本,一般来说,行数越大,压缩效果越好,比如列基数同为 11 的两张单列表,一亿行的表没有将 100 万行表的体积线性增加 100 倍,而是只有的前者的 90 倍,压缩效果更好。
查看列基数
既然列基数如此重要,手工查看和统计每列的基数显然是不切实际的,Vertipaq Analyzer 可以帮你快速查看并导出模型的基础属性数据,其中就包括 Cardinality,现在这个工具已经集成到 DAX Studio 中,下图是使用 DAX Studio 查看 Contoso 数据模型中 Sales 表的列基数分布,你可以将其导出到 Excel
优化列基数的建议
在设计数据模型时,应该考虑列基数的影响,如果要在关系、筛选器或计算中使用列,考虑采取可能的优化措施,在允许的范围内减少列的基数,这可以显著提升性能表现,以下优化建议可供参考:
关系的基数 Cardinality of the Relationships
关系的基数是根据关系两侧的列是否具有重复值定义的,用于划分关系的类型。这个概念来自数据建模,在 DAX 中,关系有三种基数类型,它们在技术上和语义上都有一定的区别。在这里,我们不做深入讨论,只是阐述基数在这个语境下的含义:
- 一对多关系:这是最常见的基数类型。在关系的一端,列必须具有唯一值;在关系的多端,通常包含重复值。
- 一对一关系:这是一种相当少见的基数类型。关系两端的列都具有唯一值。
- 多对多关系:关系两端的列可以有多个重复值。这个功能是在 2018 年引入的,遗憾的是,它的名字有点令人困惑。在公共数据建模语言中,“多对多”指的是另一种不同的实现方式,它是使用一对多和多对一创建的关系。重要的是要理解,在这个场景中,many-to-many 不是指多对多关系,而是指关系中的多对多基数类型。
高关于100W行11个不重复值和1亿行11个不重复值,我进行了测试。我发现两者的文件大小几乎一致,差异非常非常小。并没有行数增加100倍,文件增加90倍的情况,而是文件大小几乎不增加。我也测试了11个数字和10亿行11个不重复值的文件大小,几乎没有差异。
高老师,有个疑问, 基数对性能的影响 和 模型中建议有主键、外键及索引是不是有矛盾。通常规范模型后,行数定了(无重复),列数定了,关系定了,是不是意味着基数也就定了。
优化关系列中,指出反规范化的方法优化模型,请问,这个反规范化是要怎么理解,有没有样例?我这边经常要用到ID关联的,基数都在50w+