文章 查看内容

如何通过元数据统计全局参数在哪些数据集、卡片、页面中被使用 ...

如何通过元数据统计全局参数在哪些数据集、卡片、页面中被使用 ...

31 0 其他 2026-6-30 16:03 发布者: Chansey

一. 背景与目标在删除或调整全局参数前,管理员需要知道该全局参数是否仍被下游资源使用,以及影响范围在哪里。常见影响对象包括:数据集:数据集 SQL、存储过程、参数化查询等引用了全局参数。卡片:卡片使用了带全 ...

一. 背景与目标

在删除或调整全局参数前,管理员需要知道该全局参数是否仍被下游资源使用,以及影响范围在哪里。常见影响对象包括:

  • 数据集:数据集 SQL、存储过程、参数化查询等引用了全局参数。
  • 卡片:卡片使用了带全局参数的数据集,或卡片自身配置里直接引用了全局参数。
  • 页面:页面中包含了使用全局参数的卡片。

本文说明如何通过元数据表统计全局参数的使用情况,并判断下游引用是否有效。

核心原则:

先从下游配置中抽取 dpId,再反查 dynamic_parameter 主表。

不要只从 dynamic_parameter 主表往下查。原因是:如果全局参数已经被删除,主表中可能已经没有该参数记录,此时从主表出发无法发现下游残留引用。正确做法是从数据集、卡片等下游配置中先抽取残留的 dpId,再通过 LEFT JOIN dynamic_parameter 判断该引用是否仍有效。

二. 核心标识与判断口径

全局参数应通过 ID 关联,而不是通过名称关联。

主关联键:

dpId + domId

原因:

  • dpId 是全局参数的稳定标识。
  • name 可能改名、重复,不适合作为关联键。
  • domId 用于避免跨租户或跨域误关联。
  • 参数删除后,名称可能已无法从 dynamic_parameter 表获取,但下游仍可能残留 dpId

引用有效性判断:

有效引用:
下游配置中的 dpId 能 LEFT JOIN 到 dynamic_parameter.dpId + domId。

失效引用:
下游配置中仍有 dpId,但 dynamic_parameter 中查不到对应 dpId + domId。

疑似跨域/脏数据:
dpId 能在其他 domId 下查到,但当前 domId 对不上。

冻结参数:
dynamic_parameter 中能查到,但 freeze = 1。

三. 涉及的元数据表

3.1 dynamic_parameter

全局参数主表。

常用字段:

字段说明
dpId全局参数 ID
domId租户/域
name全局参数名称
value_type参数类型
default_value默认值
freeze是否冻结

3.2 data_source

数据集主表。

常用字段:

字段说明
ds_id数据集 ID
dom_id租户/域
name数据集名称
config数据集配置 JSON
is_del是否删除

全局参数常见存储位置:

data_source.config.dynamicParameters

3.3 card

卡片主表。

常用字段:

字段说明
cd_id卡片 ID
dom_id租户/域
name卡片名称
ds_id卡片主数据集 ID
meta卡片图表配置 JSON
settings卡片联动、高级配置 JSON
raw_data部分卡片扩展配置
is_del是否删除

卡片直接使用全局参数的常见位置:

card.meta.chartMain.props.dynamicParameters
card.meta 中筛选条件的 dpId
card.settings 中联动目标 targetFields.dpId
card.raw_data 中的 dpId

3.4 page_card_rel

页面与卡片关系表。

常用字段:

字段说明
pg_id页面 ID
cd_id卡片 ID
dom_id租户/域
is_del是否删除

3.5 page

页面主表。

常用字段:

字段说明
pg_id页面 ID
dom_id租户/域
name页面名称
is_del是否删除

四. 全局参数使用统计

4.1 统计哪些数据集使用了全局参数

元数据关系

数据集使用全局参数的关系如下:

data_source.config.dynamicParameters[*].dpId
  -> dynamic_parameter.dpId

data_source.dom_id
  -> dynamic_parameter.domId

示例配置:

{
  "dynamicParameters": [
    {
      "dpId": "a1a7fc8181f714f119f307eb",
      "name": "城市-多值",
      "valueType": "STRING",
      "defaultValue": "上海市"
    }
  ]
}

SQL示例

WITH ds_param_ref AS (
  SELECT
    ds.dom_id,
    ds.ds_id,
    ds.name AS ds_name,
    dp_ref.dpId AS dp_id
  FROM data_source ds
  LATERAL VIEW OUTER explode(
    from_json(
      get_json_object(ds.config, '$.dynamicParameters'),
      'array<struct<dpId:string,name:string,valueType:string,defaultValue:string,fdId:string,customize:boolean,multiple:boolean,optionValue:array<string>,inheritParent:boolean>>'
    )
  ) ex AS dp_ref
  WHERE coalesce(ds.is_del, 0) = 0
    AND ds.config IS NOT NULL
    AND get_json_object(ds.config, '$.dynamicParameters') IS NOT NULL
    AND get_json_object(ds.config, '$.dynamicParameters') <> '[]'
    AND dp_ref.dpId IS NOT NULL
    AND trim(dp_ref.dpId) <> ''
)
SELECT
  ref.ds_id AS `数据集ID`,
  ref.ds_name AS `数据集名称`,
  ref.dp_id AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  CASE
    WHEN dp.dpId IS NULL THEN '失效:参数已删除或跨域'
    WHEN coalesce(dp.freeze, 0) = 1 THEN '有效:但参数冻结'
    ELSE '有效'
  END AS `引用状态`
FROM ds_param_ref ref
LEFT JOIN dynamic_parameter dp
  ON ref.dp_id = dp.dpId
 AND ref.dom_id = dp.domId;

PS:为什么使用 LEFT JOIN

这里必须使用 LEFT JOIN,不能使用 INNER JOIN

原因:

INNER JOIN 只能查到仍存在于 dynamic_parameter 表中的参数。
LEFT JOIN 可以保留下游残留的 dpId,从而发现已删除但仍被引用的参数。

4.2 统计哪些卡片使用了全局参数

卡片使用全局参数有两类口径:

  1. 卡片使用了带全局参数的数据集。
  2. 卡片自身配置里直接引用了全局参数。

建议两类都统计,并用 使用场景 字段区分。

4.2.1 卡片使用了带全局参数的数据集

元数据关系

data_source.config.dynamicParameters[*].dpId
  -> data_source.ds_id
  -> card.ds_id

即:卡片本身不一定直接配置了全局参数,但它引用的数据集使用了全局参数,因此卡片会受到该参数影响。

SQL 示例

WITH ds_param_ref AS (
  SELECT
    ds.dom_id,
    ds.ds_id,
    ds.name AS ds_name,
    dp_ref.dpId AS dp_id
  FROM data_source ds
  LATERAL VIEW OUTER explode(
    from_json(
      get_json_object(ds.config, '$.dynamicParameters'),
      'array<struct<dpId:string,name:string,valueType:string,defaultValue:string,fdId:string,customize:boolean,multiple:boolean,optionValue:array<string>,inheritParent:boolean>>'
    )
  ) ex AS dp_ref
  WHERE coalesce(ds.is_del, 0) = 0
    AND dp_ref.dpId IS NOT NULL
    AND trim(dp_ref.dpId) <> ''
)
SELECT DISTINCT
  c.cd_id AS `卡片ID`,
  c.name AS `卡片名称`,
  ref.ds_id AS `数据集ID`,
  ref.ds_name AS `数据集名称`,
  ref.dp_id AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  '卡片使用带参数数据集' AS `使用场景`,
  CASE
    WHEN dp.dpId IS NULL THEN '失效:参数已删除或跨域'
    WHEN coalesce(dp.freeze, 0) = 1 THEN '有效:但参数冻结'
    ELSE '有效'
  END AS `引用状态`
FROM ds_param_ref ref
JOIN card c
  ON c.ds_id = ref.ds_id
 AND c.dom_id = ref.dom_id
LEFT JOIN dynamic_parameter dp
  ON ref.dp_id = dp.dpId
 AND ref.dom_id = dp.domId
WHERE coalesce(c.is_del, 0) = 0;

4.2.2 卡片自身配置直接引用全局参数

标准配置路径

卡片内容中通常会有:

card.meta.chartMain.props.dynamicParameters

这里保存了卡片侧的动态参数配置。

SQL 示例:解析标准路径

WITH card_direct_dp AS (
  SELECT
    c.dom_id,
    c.cd_id,
    c.name AS card_name,
    dp_ref.dpId AS dp_id
  FROM card c
  LATERAL VIEW OUTER explode(
    from_json(
      get_json_object(c.meta, '$.chartMain.props.dynamicParameters'),
      'array<struct<dpId:string,name:string,valueType:string,defaultValue:string,fdId:string,inheritParent:boolean>>'
    )
  ) ex AS dp_ref
  WHERE coalesce(c.is_del, 0) = 0
    AND dp_ref.dpId IS NOT NULL
    AND trim(dp_ref.dpId) <> ''
)
SELECT
  ref.cd_id AS `卡片ID`,
  ref.card_name AS `卡片名称`,
  ref.dp_id AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  '卡片直接配置' AS `使用场景`,
  CASE
    WHEN dp.dpId IS NULL THEN '失效:参数已删除或跨域'
    WHEN coalesce(dp.freeze, 0) = 1 THEN '有效:但参数冻结'
    ELSE '有效'
  END AS `引用状态`
FROM card_direct_dp ref
LEFT JOIN dynamic_parameter dp
  ON ref.dp_id = dp.dpId
 AND ref.dom_id = dp.domId;

兜底扫描卡片 JSON

除标准路径外,全局参数还可能出现在:

card.meta
card.settings
card.raw_data

比如:

"dpId": "xxx"
filterType = "IN_GLOBAL_PARAMS"
filterType = "STARTSWITH_GLOBAL_PARAMS"
targetFields 中存在 dpId

如果只需要发现仍存在的全局参数,可以使用:

SELECT
  c.cd_id AS `卡片ID`,
  c.name AS `卡片名称`,
  dp.dpId AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  '卡片JSON中出现dpId' AS `使用场景`,
  '有效' AS `引用状态`
FROM card c
JOIN dynamic_parameter dp
  ON c.dom_id = dp.domId
WHERE coalesce(c.is_del, 0) = 0
  AND (
    c.meta LIKE concat('%', dp.dpId, '%')
    OR c.settings LIKE concat('%', dp.dpId, '%')
    OR c.raw_data LIKE concat('%', dp.dpId, '%')
  );

注意:该兜底方式是从 dynamic_parameter 主表出发,只能发现仍存在的参数。如果参数已经删除,需要从卡片 JSON 中先抽取所有疑似 dpId,再 LEFT JOIN dynamic_parameter

4.3 统计哪些页面使用了全局参数

页面通常不直接使用全局参数,而是因为页面上包含了相关卡片。

元数据关系

全局参数
  -> 数据集 / 卡片
  -> page_card_rel.cd_id
  -> page.pg_id

即:

card_param_ref.cd_id = page_card_rel.cd_id
page_card_rel.pg_id = page.pg_id

SQL 示例

下面 SQL 假设已经有两个中间结果:

  • ds_param_ref:数据集引用全局参数。
  • card_direct_dp:卡片直接配置全局参数。
WITH card_param_ref AS (
  SELECT
    c.dom_id,
    c.cd_id,
    c.name AS card_name,
    ref.ds_id,
    ref.ds_name,
    ref.dp_id,
    '卡片使用带参数数据集' AS usage_type
  FROM ds_param_ref ref
  JOIN card c
    ON c.ds_id = ref.ds_id
   AND c.dom_id = ref.dom_id
  WHERE coalesce(c.is_del, 0) = 0

  UNION ALL

  SELECT
    dom_id,
    cd_id,
    card_name,
    NULL AS ds_id,
    NULL AS ds_name,
    dp_id,
    '卡片直接配置' AS usage_type
  FROM card_direct_dp
)
SELECT DISTINCT
  p.pg_id AS `页面ID`,
  p.name AS `页面名称`,
  c.cd_id AS `卡片ID`,
  c.card_name AS `卡片名称`,
  c.ds_id AS `数据集ID`,
  c.ds_name AS `数据集名称`,
  c.dp_id AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  c.usage_type AS `使用场景`,
  CASE
    WHEN dp.dpId IS NULL THEN '失效:参数已删除或跨域'
    WHEN coalesce(dp.freeze, 0) = 1 THEN '有效:但参数冻结'
    ELSE '有效'
  END AS `引用状态`
FROM card_param_ref c
JOIN page_card_rel rel
  ON rel.cd_id = c.cd_id
 AND rel.dom_id = c.dom_id
JOIN page p
  ON p.pg_id = rel.pg_id
 AND p.dom_id = rel.dom_id
LEFT JOIN dynamic_parameter dp
  ON c.dp_id = dp.dpId
 AND c.dom_id = dp.domId
WHERE coalesce(rel.is_del, 0) = 0
  AND coalesce(p.is_del, 0) = 0;

⑤. 推荐统一统计 SQL 框架

实际落地时,建议统一输出一张明细表,包含数据集、卡片、页面三层信息。

推荐字段:

字段说明
全局参数ID下游配置中抽取到的 dpId
全局参数名称从 dynamic_parameter 反查得到
引用状态有效、失效、冻结等
使用层级数据集、卡片、页面
使用场景数据集配置、卡片使用带参数数据集、卡片直接配置、页面包含相关卡片
数据集ID相关数据集 ID
数据集名称相关数据集名称
卡片ID相关卡片 ID
卡片名称相关卡片名称
页面ID相关页面 ID
页面名称相关页面名称

示例统一结构:

WITH ds_param_ref AS (
  -- 数据集中的全局参数引用
),
card_direct_dp AS (
  -- 卡片自身配置中的全局参数引用
),
card_param_ref AS (
  -- 卡片使用带参数数据集
  SELECT
    ref.dom_id,
    ref.ds_id,
    ref.ds_name,
    c.cd_id,
    c.name AS card_name,
    ref.dp_id,
    '卡片' AS usage_level,
    '卡片使用带参数数据集' AS usage_type
  FROM ds_param_ref ref
  JOIN card c
    ON c.ds_id = ref.ds_id
   AND c.dom_id = ref.dom_id
  WHERE coalesce(c.is_del, 0) = 0

  UNION ALL

  -- 卡片直接配置
  SELECT
    dom_id,
    NULL AS ds_id,
    NULL AS ds_name,
    cd_id,
    card_name,
    dp_id,
    '卡片' AS usage_level,
    '卡片直接配置' AS usage_type
  FROM card_direct_dp
),
page_param_ref AS (
  SELECT
    c.dom_id,
    c.ds_id,
    c.ds_name,
    c.cd_id,
    c.card_name,
    p.pg_id,
    p.name AS page_name,
    c.dp_id,
    '页面' AS usage_level,
    concat('页面包含相关卡片:', c.usage_type) AS usage_type
  FROM card_param_ref c
  JOIN page_card_rel rel
    ON rel.cd_id = c.cd_id
   AND rel.dom_id = c.dom_id
  JOIN page p
    ON p.pg_id = rel.pg_id
   AND p.dom_id = rel.dom_id
  WHERE coalesce(rel.is_del, 0) = 0
    AND coalesce(p.is_del, 0) = 0
),
all_refs AS (
  SELECT
    dom_id,
    ds_id,
    ds_name,
    NULL AS cd_id,
    NULL AS card_name,
    NULL AS pg_id,
    NULL AS page_name,
    dp_id,
    '数据集' AS usage_level,
    '数据集配置' AS usage_type
  FROM ds_param_ref

  UNION ALL

  SELECT
    dom_id,
    ds_id,
    ds_name,
    cd_id,
    card_name,
    NULL AS pg_id,
    NULL AS page_name,
    dp_id,
    usage_level,
    usage_type
  FROM card_param_ref

  UNION ALL

  SELECT
    dom_id,
    ds_id,
    ds_name,
    cd_id,
    card_name,
    pg_id,
    page_name,
    dp_id,
    usage_level,
    usage_type
  FROM page_param_ref
)
SELECT DISTINCT
  ref.dp_id AS `全局参数ID`,
  dp.name AS `全局参数名称`,
  CASE
    WHEN dp.dpId IS NULL THEN '失效:参数已删除或跨域'
    WHEN coalesce(dp.freeze, 0) = 1 THEN '有效:但参数冻结'
    ELSE '有效'
  END AS `引用状态`,
  ref.usage_level AS `使用层级`,
  ref.usage_type AS `使用场景`,
  ref.ds_id AS `数据集ID`,
  ref.ds_name AS `数据集名称`,
  ref.cd_id AS `卡片ID`,
  ref.card_name AS `卡片名称`,
  ref.pg_id AS `页面ID`,
  ref.page_name AS `页面名称`
FROM all_refs ref
LEFT JOIN dynamic_parameter dp
  ON ref.dp_id = dp.dpId
 AND ref.dom_id = dp.domId;

六. 数据集 SQL 中涉及的函数语法

6.1 get_json_object

get_json_object(ds.config, '$.dynamicParameters')

作用:从 JSON 字符串中取出指定路径的值。

在本场景中,用于从数据集配置中取出 dynamicParameters 数组。

6.2 from_json

from_json(
  get_json_object(ds.config, '$.dynamicParameters'),
  'array<struct<dpId:string,name:string,valueType:string,defaultValue:string>>'
)

作用:把 JSON 字符串转成 Spark SQL 可识别的结构化数组。

注意:需要显式声明 schema,否则后续无法访问 dp_ref.dpId

6.3 explode

explode(array_col)

作用:把数组拆成多行。

例如一个数据集引用了 3 个全局参数,explode 后会产生 3 行。

6.4 LATERAL VIEW OUTER explode

LATERAL VIEW OUTER explode(...) ex AS dp_ref

作用:在 Spark/Hive SQL 中展开数组字段。

OUTER 的作用是:即使数组为空或为 null,也保留原始行。但如果后面加了:

dp_ref.dpId IS NOT NULL

最终仍只会保留真实引用了全局参数的记录。

6.5 coalesce

coalesce(ds.is_del, 0) = 0

作用:兼容删除标识为空的情况。

如果 is_del 是字符串类型,可以改成:

coalesce(ds.is_del, '0') = '0'

具体使用哪种写法,需要根据元数据字段类型确认。

6.6 trim

trim(dp_ref.dpId) <> ''

作用:过滤空字符串,避免无效引用进入统计结果。

6.7 concat

如果在 ETL 常规 Join 算子中不方便配置多字段关联,可以生成拼接键:

concat(dp_ref.dpId, '@@', ds.dom_id) AS dp_join_key

全局参数主表中也生成:

concat(dpId, '@@', domId) AS dp_join_key

然后在 ETL 中用单字段关联:

dp_join_key = dp_join_key

这样既保留了 dpId + domId 的关联语义,又能避免部分前端 ETL Join 面板对多字段 predicate 支持不稳定的问题。

七. 实操建议

7.1 查询口径建议

推荐分三层统计:

数据集层:data_source.config.dynamicParameters
卡片层:card.ds_id 关联数据集引用 + card.meta/settings/raw_data 直接引用
页面层:page_card_rel 关联包含相关卡片的页面

9.2 删除前检查建议

删除某个全局参数前,应检查:

1. 是否仍被数据集引用
2. 是否仍被卡片直接配置引用
3. 是否影响页面上的卡片
4. 是否存在已删除参数的残留引用

9.3 失效引用治理建议

如果发现:

下游存在 dpId,但 dynamic_parameter 中查不到

说明存在失效引用。建议治理方式:

1. 定位具体数据集、卡片、页面。
2. 确认该全局参数是否已删除。
3. 如果下游仍需要参数能力,重新绑定新的全局参数。
4. 如果下游不再需要,清理数据集或卡片配置中的残留 dpId。

10. 总结

全局参数影响范围统计的核心不是“查参数表”,而是“查下游资源中残留的参数引用”。

推荐实现链路:

1. 从 data_source.config.dynamicParameters 抽取数据集引用。
2. 从 card.meta/settings/raw_data 抽取卡片直接引用。
3. 通过 card.ds_id 找到使用带参数数据集的卡片。
4. 通过 page_card_rel 找到页面。
5. 最后 LEFT JOIN dynamic_parameter 判断引用是否有效。

最终即可形成:

全局参数 -> 数据集 -> 卡片 -> 页面

以及:

有效 / 失效 / 冻结 / 跨域异常

的完整治理视图。


路过

雷人

握手

鲜花

鸡蛋

评论

您需要登录后才可以发表言论 登录立即注册
微信服务号
联系我们
电话:400-880-0750
邮箱:hello@guandata.com
Copyright © 2001-2026 观远社区 版权所有 All Rights Reserved. 浙 ICP 备15006424号-3
去评论 去发文 返回顶部
返回顶部