关于 databricks-aibi-dashboards
用于设计、验证和部署 Databricks AI/BI 仪表板的技能,涵盖图表选择、SQL 检查、筛选器与结构规划,并说明何时应改用自定义 Databricks App。
主要功能
- 01选择标准或 Vega-Lite 图表
- 02探索表结构并验证 SQL
- 03规划数据集、筛选器和布局
- 04创建、更新并发布仪表板
适用场景
- 01构建 KPI 和趋势仪表板
- 02呈现队列留存或任务排期
- 03部署前检查查询
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ databricks/ databricks-agent-skills --skill databricks-aibi-dashboards安装后在 Claude Code 中输入/databricks-aibi-dashboards确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlassets/databricks.svgreferences/1-widget-specifications.md2-advanced-widget-specifications.md3-filters.md4-examples.md5-troubleshooting.md6-custom-visualizations.md详细介绍
AI/BI 仪表板技能
创建 Databricks AI/BI 仪表板(原名 Lakeview 仪表板)。 仪表板应展示对用户有用的内容,通常在顶部展示一些 KPI,并根据内容设计展示一些图表(通常是时间图表),让用户看到“发生了什么”。 请严格遵循以下指南。
选择组件
默认使用标准组件。只有在标准组件无法呈现所需可视化效果时,才使用 Vega-Lite。通常,更换聚合方式、调色板、工具提示、参考线或小倍图并不需要自定义规范。
| 需要展示的内容 | 使用 |
|---|---|
| KPI、趋势、排名、分布或地理对比 | 标准计数器、折线图/条形图、直方图/箱线图或地图组件 |
| 带有第二坐标轴利润率折线的收入条形图 | 标准 combo |
| 按群组和经过时间段展示留存率 | 使用颜色刻度的标准 pivot |
| 按时间表展示任务开始/结束时间 | 标准 gantt |
| 配送路线或有序 GPS 轨迹 | 标准 path-map |
| 目标线或按区域重复展示同一图表 | 标准注释或分面;请参阅组件规范 |
| 每个类别都包含实际值条形和目标标记的子弹图 | custom-vega-viz;请参阅子弹图示例 |
| 以点绘制原始观测值,并叠加滚动均值线 | custom-vega-viz;请参阅分层时间序列示例 |
| 用户要求的仪表盘、雷达图或嵌套径向/旭日图布局 | custom-vega-viz;请参阅自定义图表模式 |
对于自定义图表,请确认 Vega-Lite 支持所需的图元和变换。它并不支持所有 Vega 示例或图表类型。请在数据集 SQL 中处理联接和业务计算;自定义规范用于控制返回数据的绘制方式。
何时更适合使用自定义应用: 对于基于受治理表格的只读 KPI、图表和筛选器,托管式 AI/BI 仪表板是合适的工具。如果用户需要的是自定义代码交互式应用——例如写回/数据录入、超出仪表板网格范围的专属 UI 或交互、嵌入式或需要身份验证的工作流,或者以对话式 Genie/聊天助手为主要界面——则应改用
databricks-apps技能构建 Databricks App(该技能会引入用于数据界面 UX 的databricks-app-design)。将“Ask Genie”空间链接到此仪表板仍属于本技能的范围(见下文“链接 Genie 空间”)。
快速参考
| 任务 | 命令 |
|---|---|
| 列出仓库 | databricks warehouses list |
| 列出表 | databricks experimental aitools tools query --warehouse WH "SHOW TABLES IN catalog.schema" |
| 获取架构 | databricks experimental aitools tools discover-schema catalog.schema.table1 catalog.schema.table2 |
| 测试查询 | databricks experimental aitools tools query --warehouse WH "SELECT..." |
| 创建仪表板 | databricks lakeview create --display-name "X" --warehouse-id "WH" --dataset-catalog CATALOG --dataset-schema SCHEMA --serialized-dashboard "$(cat file.json)" --json '{"parent_path": "/Workspace/Users/<you>/path"}' — --dataset-catalog / --dataset-schema 仅支持作为标志传入(必需;如果放在 --json 中,CLI 会静默忽略);parent_path 只能放在 JSON 中(没有对应标志)。查询必须使用不带限定前缀的表名。 |
| 更新仪表板 | databricks lakeview update DASHBOARD_ID --dataset-catalog CATALOG --dataset-schema SCHEMA --serialized-dashboard "$(cat file.json)" — 更新时始终重新传入 --dataset-catalog / --dataset-schema(与创建时相同,仅支持作为标志传入);更新会替换序列化的仪表板,因此省略这些参数会将每个数据集的默认值设为 null,并导致所有不带限定前缀的表查询出错。 |
| 发布 | databricks lakeview publish DASHBOARD_ID --warehouse-id WH |
| 删除 | databricks lakeview trash DASHBOARD_ID |
--warehouse标志:如果databricks experimental aitools tools query --warehouse WH "..."在你的 CLI 版本中报错unknown flag: --warehouse,请改为在环境中设置DATABRICKS_WAREHOUSE_ID=WH,并移除该标志——命令会自动从环境中读取此值。
Widget 索引(版本 + 文档位置)
版本错误 = Widget 无法使用! 这是导致仪表板出错的首要原因。
群组留存图表使用带色阶单元格样式的
pivot构建,不存在cohortwidget 类型。请参阅 2-advanced-widget-specifications.md 中的 pivot。
新建仪表板工作流
部署前,必须通过 CLI 测试所有 SQL 查询。为新建仪表板时,请遵循以下步骤中的整体逻辑——跳过验证会导致仪表板无法正常工作。
步骤 1:获取 Warehouse ID(如果尚不清楚)
# List warehouses to find one for SQL execution
databricks warehouses list
步骤 2:探索表架构和现有数据模式
优秀的仪表板始于了解数据。在这一步多花些时间——探索结果会影响步骤 4 中的设计决策(选择哪些小组件、筛选器和分组方式)。
默认使用 discover-schema——一次调用即可返回列、类型、示例行、空值计数和行数。如果你只知道架构,请先使用 query "SHOW TABLES IN ..." 列出表。
databricks experimental aitools tools discover-schema catalog.schema.orders catalog.schema.customers
仅凭示例行不足以判断该构建什么。你可以通过 databricks experimental aitools tools query --warehouse <WH> "..." 编写聚合 SQL,通常用于探查:
- 基数:候选分组列的不同值数量 → 决定采用图表颜色分组还是表格(图表的不同值不超过 8 个,详见下文“基数与可读性”)。
- 主要类别值 → 为筛选器选项和图表图例填充有意义的内容。
- 数值分布(最小值/最大值/平均值/百分位数)→ 决定使用带变化值的 KPI 还是趋势图(平缓的指标不适合用折线图,详见下文“数据变化考量”)。
- 趋势可行性:按日/周/月粒度 → 选择合适的趋势粒度。
- 故事验证——运行计划放入仪表板的聚合查询,检查结果是否平缓、为空或缺乏意义。继续之前,修正查询或调整故事。
一次调用中并行执行相互独立的探查——传入多个位置参数 SQL(和/或重复使用 --file),它们会并行运行(默认 --concurrency 8):
DATABRICKS_WAREHOUSE_ID=<WH> databricks experimental aitools tools query --output json \
"SELECT COUNT(*) FROM catalog.schema.orders" \
"SELECT region, COUNT(*) FROM catalog.schema.orders GROUP BY region ORDER BY 2 DESC LIMIT 10" \
"SELECT MIN(ts), MAX(ts) FROM catalog.schema.orders"
- 多查询模式下必须使用
--output json。每条语句返回一个对象:{sql, state, rows, error};失败按语句分别处理(state: "FAILED"),其他语句仍会成功。 - ⚠️ 不要相信退出码(某条语句失败时,退出码仍可能是
0)——应逐个检查对象,确认其state != "SUCCEEDED"。
仪表板查询有所不同——在仪表板 JSON 中,
FROM子句只能引用表名,不能带目录或架构前缀:
- ✅ 正确:
FROM trips- ❌ 错误:
FROM nyctaxi.trips- ❌ 错误:
FROM samples.nyctaxi.trips运行
databricks lakeview create时,通过--dataset-catalog和--dataset-schema标志分别指定目录和架构。这些标志不会改写查询——仅在查询省略目录/架构时填充相应信息。如果在FROM子句中写死目录或架构,则这些标志对该查询不起作用,仪表板也无法跨环境移植。
步骤 3:验证数据是否符合故事
必须测试仪表板 JSON 中的 datasets.querylines(见下方示例),以确保
在最终确定之前,请运行计划添加到每个数据集中的 SQL 查询,确认它们能正常运行且结果有效。 这至关重要,因为 JSON 中定义的小组件会使用 query 字段的输出渲染可视化内容。结果在业务层面也应合理。 请记住,要让筛选器生效,查询必须包含相应字段(因此通常应按筛选字段分组)。
如果结果与预期不符,请确认查询正确;如果可以,请修正数据,或在创建仪表板前调整故事。
第 4 步:规划仪表板结构
在编写 JSON 之前,先规划仪表板:
- 你必须了解预期的具体 JSON 结构。为此,阅读参考文件:1-widget-specifications.md、3-filters.md。
务必完整阅读一个示例以了解结构,例如 4-examples.md。
-
思考:需要哪些小组件? 将每种可视化映射到一个数据集:
小组件 类型 数据集 有筛选字段吗? 收入 KPI counter ds_sales ✓ 日期、地区 趋势图 line ds_sales ✓ 日期、地区 热门产品 table ds_products ✗ 无日期 ... -
需要哪些筛选器? 对于每个筛选器,请确认你希望进行筛选的所有数据集都包含该筛选字段。
筛选器只会影响包含筛选字段的数据集。 不带日期的预聚合表不会按日期筛选。
-
将仪表板 JSON 构建为本地工作文件(中间步骤,并非最终交付物)。
第 5 步:部署
现在将 JSON 部署到工作区。 运行 databricks lakeview create(如下所示)。只有此命令成功运行并返回仪表板 ID 后,任务才算完成——JSON 文件本身只是中间工作产物。
向用户提供仪表板链接(主机地址来自 databricks auth env -o json → .env.DATABRICKS_HOST)。请注意 v3——不带它的 /sql/dashboards/ 是错误的旧版路径:
- 草稿:
https://<host>/sql/dashboardsv3/<DASHBOARD_ID> - 已发布: 追加
/published(仅在运行databricks lakeview publish DASHBOARD_ID后有效)
部署后,可使用相同的 lakeview 子命令管理仪表板的生命周期(list、get、update、publish、trash)。
# Deploy: creates the dashboard in the workspace and returns a dashboard ID.
# Canonical form — MIX flags + --json. Each field has exactly ONE valid place:
# --dataset-catalog / --dataset-schema : FLAG-ONLY (REQUIRED — no JSON field).
# The CLI silently warns "unknown field" and drops them if put in --json,
# leaving every dataset query unable to resolve its catalog.schema.
# parent_path : JSON-ONLY (no flag). Without it, dashboard lands at
# /Users/<you>/<display-name>.
# display_name / warehouse_id / serialized_dashboard : either form works;
# prefer flags for readability.
# Queries inside dashboard.json MUST use bare table names ("FROM trips", never
# "FROM schema.trips" or "FROM catalog.schema.trips") — --dataset-catalog and
# --dataset-schema only fill in missing parts, they do NOT rewrite hardcoded
# prefixes.
#
# parent_path must ALREADY EXIST or create fails "Tree node ... does not exist":
databricks workspace mkdirs /Workspace/Users/[email protected]/dashboards
# Capture the dashboard_id with -o json. Do NOT add 2>&1: create echoes the
# serialized dashboard back, and merging stderr breaks the output so jq can't
# parse it (the dashboard IS created, but you lose the id and the step looks failed).
DASHBOARD_ID=$(databricks lakeview create \
--display-name "My Dashboard" \
--warehouse-id "abc123def456" \
--dataset-catalog "my_catalog" \
--dataset-schema "my_schema" \
--serialized-dashboard "$(cat dashboard.json)" \
--json '{"parent_path": "/Workspace/Users/[email protected]/dashboards"}' \
-o json | jq -r '.dashboard_id')
# List all dashboards
databricks lakeview list
# Get dashboard details
databricks lakeview get DASHBOARD_ID
# Update a dashboard
# ALWAYS re-pass --dataset-catalog / --dataset-schema: update replaces the
# serialized dashboard, so omitting them nulls the defaults and breaks queries.
databricks lakeview update DASHBOARD_ID \
--dataset-catalog "my_catalog" \
--dataset-schema "my_schema" \
--serialized-dashboard "$(cat dashboard.json)"
# Publish a dashboard
databricks lakeview publish DASHBOARD_ID --warehouse-id WAREHOUSE_ID
# Unpublish a dashboard
databricks lakeview unpublish DASHBOARD_ID
# Delete (trash) a dashboard
databricks lakeview trash DASHBOARD_ID
# By default, after creation, tag dashboards to track resources created with this skill
databricks workspace-entity-tag-assignments create-tag-assignment \
dashboards DASHBOARD_ID aidevkit_project --tag-value ai-dev-kit
更新现有仪表板
要更改现有仪表板,请按照上文的创建工作流构建更新后的 JSON,然后使用同一个 DASHBOARD_ID 运行 update + publish 进行部署——切勿重新运行 create/import。
- 不要通过
create/import 来更新。 这会创建新的仪表板 ID 和 URL,并使你已分享的链接失效;create仅用于创建全新仪表板。 update只会更改草稿。 查看者看到的/published链接仍会指向上一个快照,直到你再次运行publish——因此,update后务必运行publish。
JSON 结构(必需框架)
每个仪表板的 serialized_dashboard 内容都必须遵循以下确切结构:
重要提示:务必在每个 queryLines 值末尾添加空格或 \n,因为这些值会串联起来创建数据集。
{
"datasets": [
{
"name": "ds_x",
"displayName": "Dataset X",
"queryLines": ["SELECT col1, col2 ", "FROM my_table"]
}
],
"pages": [
{
"name": "main",
"displayName": "Main",
"pageType": "PAGE_TYPE_CANVAS",
"layout": [
{"widget": {/* INLINE widget definition */}, "position": {"x":0,"y":0,"width":2,"height":3}}
]
}
]
}
结构规则(违反会导致“failed to parse serialized dashboard”):
queryLines:字符串数组,而不是"query": "string"。各元素会直接拼接,中间不添加分隔符——每行末尾都要添加或\n(或者删除--注释)。如果某行以-- comment结尾且没有换行符,后续内容会被注释吞掉。- 小组件:必须内嵌在
layout[].widget中,不能放在单独的"widgets"数组中 pageType:每个页面都必须设置(PAGE_TYPE_CANVAS或PAGE_TYPE_GLOBAL_FILTERS)- 查询绑定:图表、表格、计数器和自定义可视化的
query.fields[].name值必须与encodings.*.fieldName值完全一致。筛选器的绑定方式因小组件类型而异;范围滑块会通过一个底层fieldName暴露MIN/MAX查询字段,绑定参数的日期筛选器则使用query.parameters。
主题和颜色(务必设置——这会直接影响仪表板效果)
顶层的 uiSettings.theme 控制仪表板中所有小组件的颜色、字体和外观。若不设置,仪表板会继承工作区默认主题,显得千篇一律。创建每个仪表板时都要设置完整配置块——协调一致的配色方案是提升质感最有效的方式。
思维模型——将60/30/10 规则映射到主题键:60% 中性色=画布/组件/边框背景(设置 widgetBorderColor = widgetBackgroundColor 可隐藏边框);30% 次要色=fontColor + visualizationColors(内容的视觉权重);10% 强调色=用于筛选器/选项卡/当前选中项的 selectionColor——选择一种与文本和调色板都明显不同的颜色;接近 #2272B4 的稳妥蓝色符合超链接惯例,可作为默认选择。
{
"datasets": [...],
"pages": [...],
"uiSettings": {
"theme": {
"canvasBackgroundColor": {"light": "#FCFCFC", "dark": "#1F272D"},
"widgetBackgroundColor": {"light": "#FFFFFF", "dark": "#11171C"},
"fontColor": {"light": "#11171C", "dark": "#E8ECF0"},
"selectionColor": {"light": "#2272B4", "dark": "#8ACAFF"},
"visualizationColors": [
"#FFA600", "#FF7054", "#DE5582", "#995495",
"#4E5185", "#1D425C", "#99DDB4"
],
"widgetHeaderAlignment": "LEFT"
}
}
}
主题键(机制):
visualizationColors:有序调色板,所有图表系列和类别映射都会按顺序循环使用其中的颜色。位置从 0 开始计数:position: 0= 第一种颜色(上方的#FFA600),position: 6= 第七种颜色(#99DDB4)。通常使用 5–8 种颜色。- 背景色/字体颜色/选中色都采用
light+dark配对;仪表板会根据查看者模式自动选择。 fontColor也决定计数器数字的颜色——计数器没有单独的组件颜色设置,因此只能通过它调整(它会为仪表板上所有计数器的值着色,而非仅作用于单个图块)。widgetHeaderAlignment:"LEFT"(默认)、"CENTER"或"RIGHT"。可选的顶层设置:fontFamily(例如"Space Grotesk"、"Inter"——无衬线字体能让密集数据更易读;不要按组件覆盖)和widgetCornerRadius(整数像素值,例如圆角设为12;设为0或省略即为直角)。- 按组件指定颜色的引用(仅限图表):
{"themeColorType": "visualizationColors", "position": N}(位置从 0 开始计数),可固定使用某个调色板位置;也可使用{"hex": "#FF0000"}指定调色板之外的精确颜色。计数器不支持按组件指定颜色——在计数器的value上设置color会使组件显示为“unsupported widget definition”;请通过上文的fontColor为计数器着色。
调色板设计规则(这是精致仪表板与杂乱仪表板的区别所在):
- 每个仪表板使用一个协调的色系,并确保不同仪表板之间各有特色。沿着色相变化(例如琥珀色 → 珊瑚色 → 粉色 → 紫色 → 藏蓝色),而不是将单一颜色逐渐淡化至白色——单色系的明度渐变看起来像同一种颜色,查看者难以区分类别。相邻色阶必须在视觉上易于区分:眯眼观察时,如果两种颜色融为一体,就应拉大它们的差异。单色系渐变仅用于定量组件(
colorRamp.mode: "custom-sequential"),不要用于visualizationColors。 - 将语义颜色固定为调色板之外的十六进制字面值。“差”=暖珊瑚色(例如
#FF7E5C),“好”=平和的青绿色/绿色。使用color.scale.mappings并填写纯十六进制字符串——{"value": "Critical", "color": "#FF7E5C"}——不要使用{"hex": "..."}或themeColorType: position(图表组件会静默丢弃这两种设置)。复用调色板中已有的青绿色,避免产生冲突。 - **为非类别型组件明确指定颜色,使其融入色系。**地图和热力图:使用
colorRamp.mode: "custom-sequential",并从色系中选择{start, end}(如果颜色表示方向性,start= 差的颜色,end= 好的颜色)。预测/多系列:通过以displayName为键的color.scale.mappings固定每个系列的颜色(实际值 = 色系中的纯色,预测值 = 对比色/警示色,阈值 = 柔和色调)。计数器(包括迷你趋势图计数器)不接受按组件指定颜色——其数字颜色来自主题的fontColor;不要设置value.color(这会显示“unsupported widget definition”)。 - “更浅/更柔和”的调整:整体提高所有色阶的明度,不要单独更改某一种颜色。重新同步固定的语义十六进制值;警示色仍须有足够的对比度,确保其警示效果清晰。
入门调色板(选择一种并按需调整——必要时扩展到 7–8 种颜色;根据规则 2,语义红/绿仍须使用十六进制字面值):
#094074 #3C6997 #5ADBFF #FFDD4A #FE9000
#003F5C #594E90 #BC4C96 #FF5F66 #FFA600
#4A8CC7 #F59770 #FFD84A #F0E09E #6DD980
#440154 #3B528B #21918C #5EC962 #FDE725
#4E79A7 #F28E2C #E15759 #76B7B2 #59A14F
#0072B2 #E69F00 #009E73 #CC79A7 #D55E00
#0D0887 #7E03A8 #CC4778 #F89441 #F0F921
#6929C4 #1192E8 #005D5D #9F1853 #FA4D56
约有 4–5% 的查看者存在色觉缺陷(主要是红/绿色盲)。上方第 4 行和第 6 行(viridis、Okabe-Ito)在设计上对色盲友好;自定义调色板可通过模拟器(Adobe Color、colorbrewer2.org)进行验证。不要让红色和绿色相邻;相邻色阶之间应依靠明度对比,而不只是色相差异。
链接 Genie Space(可选)
要在仪表板中添加“Ask Genie”按钮,或通过 ID 链接 genie space/room,请在 JSON 中添加 uiSettings.genieSpace(如果有 theme,则与其并列):
"uiSettings": {
"theme": { /* ... */ },
"genieSpace": {
"isEnabled": true,
"overrideId": "your-genie-space-id-here",
"enablementMode": "ENABLED"
}
}
Genie 不是小组件。 只能通过
uiSettings.genieSpace链接。不存在"widgetType": "assistant"。
设计最佳实践
除非用户另有指定,否则请遵循以下原则:
- 全局日期筛选器:如果数据包含时间列,请添加日期范围筛选器。大多数仪表板都需要基于时间进行筛选。
- KPI 时间范围:使用支持周期比较(环比、同比)的限时指标。没有时间限制的“历史总计”可操作性较低。
- 数值格式:根据数值含义设置格式——货币添加符号,百分比使用 %,大数使用简洁格式(K/M/B)。
- 图表选择:根据基数选择图表类型。不同值较少 → 使用带颜色分组的条形图(如果确实只想展示快照,也可使用饼图);不同值较多 → 使用表格。
参考文件
生成任何仪表板 JSON 之前,请先阅读 4-examples.md。 这是一个完整的参考仪表板,展示了各种构造:数据集度量值 +
MEASURE()、迷你图计数器、带注释的预测线、带条件单元格的数据透视表、符号地图、直方图、范围滑块筛选器和主题。请通过它了解 JSON 结构,然后根据用户的数据和演示场景进行调整——保留结构,并针对当前案例替换表、指标、配色方案和叙述内容。
| 要构建什么? | 参考资料 |
|---|---|
| 从这里开始——完整可用的仪表板模板 | 4-examples.md |
| 任意小组件(文本、计数器、表格、图表) | 1-widget-specifications.md |
| 高级图表(面积图、散点图/气泡图、组合图、甘特图、分级统计图/路径地图) | 2-advanced-widget-specifications.md |
| 带筛选器的仪表板(全局或页面级) | 3-filters.md |
| 自定义 Vega-Lite 小组件(分层图表、子弹图、仪表盘图、雷达图、旭日图) | 6-custom-visualizations.md |
| 调试故障仪表板 | 5-troubleshooting.md |
实施指南
1) 数据集架构
- 数据集越少越好——目标是用一个数据集支持尽可能多的可视化组件。 点击图表上的一个值(例如柱形或扇区),会将其作为筛选条件应用于该数据集,所有共享同一数据集的其他可视化组件都会根据该点击重新渲染。将可视化组件拆分到许多范围狭窄的数据集中会破坏这种交叉筛选功能,并迫使用户设置本应「开箱即用」的显式筛选组件。优先为每个业务领域(订单、案例、客户)使用一个宽表数据集;只有在某个可视化组件确实需要不同粒度、预聚合或其他组件无法接受的参数时,才拆分数据集。
- 定义数据集的两种方式:
- SQL 查询:
{"name": "ds_x", "displayName": "...", "queryLines": ["SELECT ...", "FROM table"]}— 控制力完整,可包含WITH/JOIN/AI_FORECAST等。 - UC 资产简写:
{"name": "ds_x", "asset_name": "catalog.schema.table_or_view"}— 无需 SQL。适用于表、视图和指标视图。还可以在此基础上叠加columns(度量 + 派生维度):{"name": "ds_x", "asset_name": "...", "columns": [{"displayName": "Total Revenue", "expression": "SUM(\amount_usd`)"}]}— 同样使用MEASURE()` 模式。
- SQL 查询:
- 使用
queryLines时,每个数据集必须恰好包含一个有效的 SQL 查询(不得用;分隔多个查询) - 查询只能使用不带限定符的表名——不能带目录或架构前缀。例如:
FROM orders,不能是FROM gold.orders或FROM main.gold.orders。目录和架构由创建时的--dataset-catalog和--dataset-schema标志指定。这些标志只会补全缺失部分,不会覆盖查询中写明的目录或架构。 - SELECT 必须包含可视化组件所需的所有维度,以及通过
AS别名定义的所有派生列 - 将所有业务逻辑(CASE/WHEN、COALESCE、比率)放入数据集 SELECT 中,并为其显式指定别名
- 可视化组件契约规则:对于图表、表格、计数器和自定义可视化组件,每个
fieldName都必须与对应的query.fields[].name匹配;该查询字段的表达式引用数据集列或别名。请遵循 3-filters.md 中针对筛选器的契约,包括范围滑块和参数绑定例外情况。 - 当可视化效果依赖数据顺序时,添加 ORDER BY:
- 时间序列:使用
ORDER BY date按时间顺序显示 - 排名/前 N 项:对于「前 10」图表,使用
ORDER BY metric DESC LIMIT 10 - 分类图表:使用
ORDER BY metric DESC,优先显示数值最大的类别
- 时间序列:使用
数据集级别的度量 + MEASURE()
可视化组件表达式通常使用内联聚合({"name": "sum(x)", "expression": "SUM(\x`)"}`)。但也可以直接在数据集上声明可复用的度量,并按名称引用——每个使用该数据集的可视化组件都可以使用同一指标,无需重新定义。
定义度量的两种方式:
-
仪表板级别的
columns(适用于任何数据集——SQL 查询或asset_name):{ "name": "ds_support", "queryLines": ["SELECT * FROM support_cases"], "columns": [ {"displayName": "Total Cases", "description": "Count of cases", "expression": "COUNT(`case_id`)"}, {"displayName": "Reopen Rate %", "description": "% of reopened cases", "expression": "SUM(CASE WHEN `reopened_flag` THEN 1 ELSE 0 END) * 100.0 / COUNT(`case_id`)"}, {"displayName": "Priority Level", "description": "Sorted priority label", "expression": "CASE WHEN `priority`='Critical' THEN '1-Critical' ELSE '4-Low' END"} ] } -
指标视图数据源——如果数据集的
asset_name(或FROM子句)是 UC 指标视图,则可以直接查询其中通过 YAML 定义的度量。不要在columns中重新声明这些度量。请参阅 databricks-metric-views。
无论采用哪种方式,可视化组件都可以按名称引用度量:
"fields": [{"name": "measure(Total Cases)", "expression": "MEASURE(`Total Cases`)"}],
"encodings": {"value": {"fieldName": "measure(Total Cases)", "displayName": "Total Cases"}}
MEASURE(\...`)` 适用于计数器、表格、柱状图、折线图、饼图、透视表等任何接受字段表达式的可视化组件。可以自由混用内联聚合。
2)小组件字段表达式
关键:字段名称匹配规则 对于图表、表格、计数器和自定义可视化小组件,
query.fields中选定的每个name都必须与encodings中的fieldName完全匹配。 如果二者不匹配,小组件会显示“没有选定可视化字段”错误!
对于 custom-vega-viz,还需将 spec.encodings.fields[].fieldName 与 Vega-Lite 输入的 field 名称匹配。将 spec.data.queryName 设置为小组件查询名称。内部的 Vega-Lite 规范读取 data.name: "databricks_query",并以 JSON 字符串形式存储在 spec.jsonSpec.spec 中。生成自定义小组件前,请先阅读 6-custom-visualizations.md。
聚合的正确模式:
// In query.fields:
{"name": "sum(spend)", "expression": "SUM(`spend`)"}
// In encodings (must match!):
{"fieldName": "sum(spend)", "displayName": "Total Spend"}
错误示例——名称不匹配:
// In query.fields:
{"name": "spend", "expression": "SUM(`spend`)"} // name is "spend"
// In encodings:
{"fieldName": "sum(spend)", ...} // ERROR: "sum(spend)" ≠ "spend"
小组件查询中允许使用的表达式(表达式中不能使用 CAST 或其他 SQL):
{"name": "(sum|avg|count|countdistinct|min|max)(col)", "expression": "(SUM|AVG|COUNT|COUNT(DISTINCT)|MIN|MAX)(`col`)"}
{"name": "(daily|weekly|monthly)(date)", "expression": "DATE_TRUNC(\"(DAY|WEEK|MONTH)\", `date`)"}
{"name": "field", "expression": "`field`"}
如果需要条件逻辑或多字段公式,请先在数据集 SQL 中计算派生列。
部分小组件支持其他表达式:甘特图可对状态字段使用 FIRST(...),几何地图绑定则需要 ST_ASGEOJSON(...)。关于这些形式,请参阅相应的小组件参考文档。
3)SPARK SQL 模式
- 日期运算:天数使用
date_sub(current_date(), N),月数使用add_months(current_date(), -N) - 日期截断:
DATE_TRUNC('DAY'|'WEEK'|'MONTH'|'QUARTER'|'YEAR', column) - 避免使用
INTERVAL语法——改用函数
4)布局(12 列网格,无间隙)
每个页面都必须在 pageType 旁包含 "layoutVersion": "GRID_V1"。
{
"name": "overview",
"displayName": "Overview",
"pageType": "PAGE_TYPE_CANVAS",
"layoutVersion": "GRID_V1",
"layout": [...]
}
每个小组件都有一个位置:{"x": 0, "y": 0, "width": 4, "height": 4}
**根据受众选择网格划分方式。**12 列网格可整齐地划分为 3、4 或 6 列:3 列布局(每个小组件的 width: 4)可降低认知负担,适合高管概览;4 列(width: 3)是通用选择;6 列(width: 2)可最大限度提高信息密度,适合读者需要同时查看大量指标的技术或运营仪表板。
默认规则:每一行的宽度都应恰好填满 12 列,不留间隙。熟悉网格后,可以让各列的高度错落排列(左侧放置一个较高的小组件,右侧搭配多个较矮的小组件),使两半不共享行边界——参见 4-examples.md 中的模式。先从严格的行布局开始;只有在错落排列的视觉效果更好时再放宽规则。
CORRECT: WRONG:
y=0: [w=12] y=0: [w=8]____ ← gap!
y=1: [w=4][w=4][w=4] ← fills 12 y=1: [w=2][w=2][w=2][w=2]__ ← gap!
y=4: [w=6][w=6] ← fills 12
推荐的小组件尺寸:
| 小组件类型 | 宽度 | 高度 | 备注 |
|---|---|---|---|
| 文本标题 | 12 | 1 | 全宽;标题和副标题应使用单独的小组件 |
| 计数器/KPI | 4 | 3-4 | 高度绝不能为 2——空间太局促! |
| 折线图/条形图/面积图 | 6 | 5-6 | 并排放置以填满一行 |
| 饼图 | 6 | 5-6 | 需要留出图例空间 |
| 全宽图表 | 12 | 5-7 | 用于详细的时间序列 |
| 表格 | 12 | 5-8 | 使用全宽以提高可读性 |
标准仪表板结构:
y=0: Title (w=12, h=1) - Dashboard title (use separate widget!)
y=1: Subtitle (w=12, h=1) - Description (use separate widget!)
y=2: KPIs (w=4 each, h=3) - 3 key metrics side-by-side
y=5: Section header (w=12, h=1) - "Trends" or similar
y=6: Charts (w=6 each, h=5) - Two charts side-by-side
y=11: Section header (w=12, h=1) - "Details"
y=12: Table (w=12, h=6) - Detailed data
5)基数与可读性(关键)
仪表板的可读性取决于对不同值数量的限制:
| 维度类型 | 最大值数量 | 示例 |
|---|---|---|
| 图表颜色/分组 | 3-8 | 4 个地区、5 条产品线、3 个层级 |
| 筛选器 | 4-15 | 8 个国家、5 个渠道 |
| 高基数 | 仅限表格 | customer_id、order_id、SKU |
创建任何使用颜色或分组的图表之前:
- 使用 discover-schema 或 COUNT DISTINCT 查询检查列的基数
- 如果不同值超过 10 个,则汇总到更高层级,或使用 TOP-N + “其他”类别
- 对于高基数维度,请使用表格小组件而非图表
6)质量检查清单
部署前,请确认:
- 所有小组件名称仅使用字母数字字符、连字符和下划线
- 每个页面都有
"layoutVersion": "GRID_V1" - 所有行的宽度之和为 12,且没有间隙
- KPI 的高度为 3-4,图表的高度为 5-6
- 图表维度的基数合理(颜色/分组不超过 8)
- 所有小组件查询表达式都引用现有数据集列或别名
- 可视化字段绑定必须完全匹配:对于图表、表格、计数器和自定义可视化,每个
query.fields[].name都与其编码中的fieldName匹配(例如,两者都是"sum(spend)")。过滤器则需根据其小组件专属约定进行验证。 - 计数器数据集:对于 1 行数据集,使用
disaggregated: true;对于多行数据集,使用disaggregated: false并进行聚合 number-percent格式的百分比值必须为 0-1(0.865 会显示为“86.5%”,别忘了设置格式)。如果数据为 0-100,请在 SQL 中除以 100,或改用number格式。- SQL 使用 Spark 语法(使用 date_sub,而非 INTERVAL)
- 所有 SQL 查询都已通过 CLI 测试,并返回预期数据
- 每个需要应用筛选器的数据集都必须包含筛选字段——筛选器只会影响查询中包含该列的数据集
abbreviation: "compact"需要设置decimalPlaces——否则数值不会进行舍入(会呈现为$9.756278496M,而不是$9.76M)
数据方差注意事项
创建趋势图之前,请检查指标是否具有足够的方差,以便清晰呈现:
SELECT MIN(metric), MAX(metric), MAX(metric) - MIN(metric) as range FROM dataset
如果相对于量表范围而言,数值区间很小(例如,在 0-100 的量表上为 83-89%),图表看起来会几乎是平的。可以考虑:
- 使用带有变化量/对比值的 KPI 代替图表
- 使用表格显示精确值
- 调整可视化,以突出方差
相关技能
- databricks-apps - 当用户需要自定义代码的交互式应用(写回、定制 UI、应用内聊天 / Genie),而非托管仪表板时
- databricks-unity-catalog - 用于查询底层数据和系统表
- databricks-pipelines - 用于构建为仪表板提供数据的数据管道
- databricks-jobs - 用于安排仪表板数据刷新