Amazon QuickSight 新增的 Multi-Dataset Relationships 让 Topic 可以理解多个数据集之间的逻辑关系,并在查询运行时执行 join。这个变化的核心不是“多了一个 join 功能”这么简单,而是 BI 建模方式从“提前做一张大宽表”转向“保留业务表边界,在语义层声明关系”。
对做 QuickSight Q、Topic 和自助分析的团队来说,这能减少很多 ETL 里的重复建模,也会把一部分建模责任转移到 QuickSight Topic 里:表之间怎么连、粒度是否一致、哪些字段能安全聚合,都要说清楚。
宽表不是消失了,而是不再是唯一答案
过去很多 QuickSight 项目会先在 Glue、Athena、Redshift 或 ETL 任务里把事实表、维表、派生指标拍成一张或几张宽表,再导入 QuickSight Dataset。这样做有明显好处:查询简单、权限边界清晰、仪表板作者不容易 join 错。
但代价也很硬:
- 每新增一个分析视角,都可能要改 ETL 或新增物化表。
- 同一张客户表、产品表、组织表会被重复拼进多个宽表。
- Topic 面向自然语言提问时,宽表字段越来越多,语义解释反而更难维护。
- 事实表之间如果粒度不同,提前 flatten 容易制造重复计数。
Multi-Dataset Relationships 的思路是:客户、订单、产品、区域这些表可以继续作为独立 QuickSight dataset 存在;你在 Topic 中声明它们的逻辑关系,QuickSight 在查询时根据问题需要组合数据集。
这更接近现代语义层建模:数据表仍然按业务边界存在,Topic 负责表达“这些表如何一起回答问题”。
关系建模要从“业务粒度”开始
运行时 join 并不意味着可以随意把表连起来。最容易出问题的是粒度不一致。
举个典型模型:
orders:订单事实表,一行一个订单。order_items:订单明细事实表,一行一个订单商品。customers:客户维表,一行一个客户。products:商品维表,一行一个商品。
orders -> customers 通常是多对一;order_items -> products 也是多对一。这样的关系比较适合在 Topic 里表达。
但如果你把 orders 和 order_items 同时放进 Topic,就要明确:
- 订单金额来自
orders还是由order_items汇总? - 如果按产品类别分析订单数,是否允许从明细表反推订单?
- 一个问题同时引用订单级指标和明细级字段时,是否会造成重复计数?
多数据集关系解决的是“表可以分开维护、按需 join”,不是自动解决所有语义歧义。Topic 里的关系声明应当配合字段描述、同义词、默认聚合方式和业务命名一起维护。
可以这样实践:先用 Athena 检查关系是否干净
在把关系放进 QuickSight Topic 之前,建议先在数据源侧验证主外键质量。下面示例假设数据在 Athena 中,数据库名为 analytics,表名为 orders 和 customers。运行前把数据库和字段名改成你的实际名称。
aws athena start-query-execution \
--query-string "
SELECT
COUNT(*) AS order_rows,
COUNT(c.customer_id) AS matched_customer_rows,
COUNT(*) - COUNT(c.customer_id) AS missing_customer_rows
FROM analytics.orders o
LEFT JOIN analytics.customers c
ON o.customer_id = c.customer_id
" \
--query-execution-context Database=analytics \
--result-configuration OutputLocation=s3://YOUR_ATHENA_QUERY_RESULTS_BUCKET/quicksight-model-checks/
再检查维表 key 是否唯一:
aws athena start-query-execution \
--query-string "
SELECT customer_id, COUNT(*) AS row_count
FROM analytics.customers
GROUP BY customer_id
HAVING COUNT(*) > 1
LIMIT 50
" \
--query-execution-context Database=analytics \
--result-configuration OutputLocation=s3://YOUR_ATHENA_QUERY_RESULTS_BUCKET/quicksight-model-checks/
如果第二个查询返回了结果,说明 customers.customer_id 不是稳定的一对一维表 key。把这种字段声明成多对一关系,会让运行时 join 的结果不可靠,尤其是金额、订单数、客户数这类指标。
也可以用 AWS CLI 先列出 QuickSight 账号中已有的数据集,确认哪些表应该作为独立 dataset 进入 Topic:
aws quicksight list-data-sets \
--aws-account-id YOUR_AWS_ACCOUNT_ID \
--region us-east-1 \
--query 'DataSetSummaries[].{Name:Name,DataSetId:DataSetId,ImportMode:ImportMode}' \
--output table
把 YOUR_AWS_ACCOUNT_ID 和 region 换成你的账号与区域。这个命令不会创建关系,只是帮助你盘点当前可用于建模的数据集。
Topic 里的关系应该像接口一样被审查
Multi-Dataset Relationships 位于 QuickSight Topic 内,这意味着它影响的是自然语言分析、字段解释和查询生成路径。建议把它当成一个语义接口,而不是 UI 里的临时配置。
可以用一个轻量清单记录每条关系。下面是一个可改造的 YAML 示例,用于代码评审或数据建模评审;它不是 QuickSight 官方配置格式,而是团队内部文档格式。
# quicksight-topic-relationships.review.yaml
# Assumption: internal review document, not a QuickSight import format.
topic: sales_analytics
relationships:
- name: orders_to_customers
left_dataset: orders
right_dataset: customers
join_keys:
- left: customer_id
right: customer_id
expected_cardinality: many_to_one
business_grain:
left: one row per order
right: one row per customer
safe_measures:
- orders.order_count
- orders.net_sales
- customers.customer_count
risk_notes:
- customer_id must be unique in customers
- avoid summing customer-level attributes after joining to orders
- name: order_items_to_products
left_dataset: order_items
right_dataset: products
join_keys:
- left: product_id
right: product_id
expected_cardinality: many_to_one
business_grain:
left: one row per order line item
right: one row per product
safe_measures:
- order_items.quantity
- order_items.line_revenue
risk_notes:
- product_id must be stable across product catalog updates
这种文档的价值在于让 BI 开发、数据工程和业务 owner 对同一个问题达成一致:这条关系到底能回答什么问题,不能回答什么问题。
采用建议:少建关系,建准关系
Multi-Dataset Relationships 最适合从高价值 Topic 开始试点,比如销售、客户成功、财务运营这类字段多、维表复用频繁的领域。
落地时可以按这个顺序推进:
- 先选择 3 到 5 个最稳定的数据集,不要一上来把整个数仓搬进 Topic。
- 优先声明事实表到维表的多对一关系,少碰事实表到事实表的复杂关系。
- 在数据源侧检查 key 唯一性、空值比例和未匹配行。
- 为 Topic 字段补充业务名称、描述、同义词和默认聚合方式。
- 用真实业务问题回归测试,例如“按区域看本季度净销售额”“购买某产品类别的新客户数”。
它的边界也很清楚:运行时 join 会把建模灵活性带到查询阶段,但错误的关系、模糊的粒度和不稳定的 key 也会在查询阶段暴露出来。不要把它当作替代数据治理的捷径。更好的用法是:让 ETL 保持清爽,让 QuickSight Topic 承担清晰、可审查的语义关系。