一句话回答
基数是集合里不同元素的个数。在数据分析里通常指一个字段或属性有多少个不同取值(设备类型低、用户 ID 或原始 URL 高);在数据建模里指一对一、一对多、多对多的表关系。
什么是基数?
基数(Cardinality)是一个集合里不同元素的个数。在数据和分析里,它有两种常见含义:
- 字段或属性的基数: 一个字段有多少个不同的取值。
device_type(电脑、手机、平板)基数低;user_id或完整页面 URL 基数高。 - 数据建模里的关系基数: 一张表的行和另一张表的行之间是多少对多少,写作一对一(1:1)、一对多(1:N)、多对多(N:M)。
数学里,基数就是集合的大小,记作 |A|。分析里的两种用法都是这个意思的延伸。
低基数和高基数
某中型产品 30 天内几个事件属性的取值数(示例数据):
| 属性 | 不同取值数 | 基数 | 适合做报表维度吗? |
|---|---|---|---|
device_type | 3 | 低 | 适合 |
browser | 31 | 低 | 适合 |
event_name | 64 | 低到中 | 适合 |
country | 187 | 中 | 适合 |
page_path(模板,如 /product/:id) | 420 | 中 | 适合 |
page_url(原始地址,带查询参数) | 186,000 | 高 | 不适合 |
user_id | 92,000 | 很高 | 不适合,用来筛选或计数 |
session_id | 1,400,000 | 很高 | 不适合 |
经验法则:按低、中基数的字段分组,按高基数的字段筛选或计数。 18 万根柱子的柱状图没人看得懂,每行只有一次访问的拆分也说明不了什么。
高基数带来的问题
- 报表看不了。 拆分只能截取前几个取值再加一个「其他」,长尾就看不到了。
- 查询变慢、成本变高。 按几百万个取值分组,意味着要对几百万个键做排序和哈希。列式存储对低基数列压缩得很好,对高基数列压缩得差。
- 指标被打散。 如果
/pricing?utm_source=x和/pricing算两个值,页面指标会被拆成几千行。 - 隐私风险。 自由文本和 ID 这类每个值都独一无二的字段可能识别到具体的人,别把邮箱、姓名写进属性。
埋点里怎么处理高基数
- 把 URL 规整成模板。 去掉查询参数,把 ID 替换掉:
/order/83721→/order/:id。活动信息放在 UTM 字段里,不要放进路径。 - 连续数值分档。 需要当维度用时,在金额之外再发一个
price_band: "50-100"。 - ID 当标识用,不当维度用。
user_id用来数去重人数、识别用户,不用来给图表分组。 - 在埋点方案里写清枚举值。 给每个属性定好允许的取值,免得「Mobile」「mobile 」「mob」这类拼写差异变成新取值。见数据分类体系和数据字典。
数去重:精确和近似
「有多少独立用户?」就是一个基数问题。精确的 COUNT(DISTINCT user_id) 要记住见过的每一个值,规模大时成本很高,而且不能按天相加:周一、周二都活跃的人是一个周活跃用户,不是两个。所以周活跃、月活跃要在整个时间窗口上计算,不能把每日数字加起来,见 DAU、WAU 和 MAU。
很多分析型数据库提供近似算法,比如 HyperLogLog,用一小块固定内存估计基数。典型相对误差约为 1.04 ÷ √m,m 是寄存器个数:16,384 个寄存器约 ±0.8%,4,096 个约 ±1.6%。看板一般够用;涉及计费、合规的计数,用精确值。
数据模型里的关系基数
| 类型 | 分析数据里的例子 | 要注意什么 |
|---|---|---|
| 一对一(1:1) | 用户和他的资料记录 | 少见,常合并成一张表 |
| 一对多(1:N) | 一个用户多次会话,一次会话多个事件 | 把事件和用户关联后,用户字段会在每条事件上重复 |
| 多对多(N:M) | 用户和他所属的多个账户 / 工作区 | 需要中间表;直接关联会重复计算收入 |
数据库的查询优化器也会估计「基数」,指某一步会返回多少行。估计不准就会选出慢的执行计划,所以统计信息要保持更新。
在 TapCub 里
TapCub 的热力图页面列表按路径模板合并;拆分图表显示前几个取值加「其他」;事件分析里属性取值很多时,只显示较常见的值。访客、人数、活跃用户这类去重计数按所选时间窗口计算,不是把每天的数字相加。在 数据 › 数据质量 的高基数页签里,系统按最近 7 天的不同取值数和阈值比较每个属性,已经接近一半的也会列出来;可以把某个属性标成仅导出,原始导出里保留,报表拆分里不再出现。分层衰减还能在旧的事件行上清空属性、来源 URL 这类高基数列,趋势和漏斗照常可用。设计属性时,报表维度保持低基数,ID 放在身份字段里。想加自己的分组维度,见自定义维度。
参考资料
- Flajolet, P., Fusy, É., Gandouet, O. and Meunier, F. (2007). HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm.
- PostgreSQL documentation. Statistics used by the planner.
- Wikipedia. Cardinality (data modeling)).
这个解释清楚吗?
我们会根据反馈修改和补充这篇内容。
提交没有成功,请稍后再试。
谢谢你的反馈,我们会据此改进这篇内容。你已经反馈过这篇了,谢谢。
