跳转至

指标加速命中说明

本文说明指标/结果加速物化在查询时的命中规则,并按查询 API 的入参给出配置说明和示例。命中只会改变查询读取的数据路径,不应改变指标口径或查询结果。

适用范围:本文面向指标查询、指标视图和看板等会使用指标/结果加速物化的场景。普通物化、外挂物化及不同版本接口的字段,以各自接口文档为准。

参数名称说明:本文以指标查询 API 的 filters 为例。部分历史接口使用 filter 字段;如接口文档明确使用 filter,请使用该接口规定的字段名,筛选表达式的命中原则不变。

1. 命中加速的基本原则

一次查询能够命中结果加速,需要由某个可用物化方案完整回答本次查询。通常需要同时满足以下条件:

校验项 核心判断规则
查询开关 请求和运行上下文未显式关闭结果加速。
方案状态 物化方案已发布上线,且物化数据至少成功生成过一次;下线方案不会参与命中。
指标(metrics 查询使用的指标均已在方案中配置,或可由已物化的辅助指标安全计算。
维度(dimensions 查询维度能由物化表表达:直接匹配、可上卷,或满足已启用的维度扩展条件。
过滤条件(filters 方案内筛选和查询筛选在物化表上仍可正确执行,不会改变指标口径。
时间范围(timeConstraint 查询时间范围被物化数据范围覆盖,且查询粒度不比物化可用粒度更细。

只要其中任一条件不满足,系统会回退到普通查询。回退不会影响结果正确性,只是不再使用物化加速。

2. 请求入参与命中的关系

下表列出与命中直接相关的常用入参。完整参数定义请参阅 API-指标数据查询

入参 是否影响命中 使用要点
metrics 所有查询指标都必须被方案覆盖。
metricDefinitions 临时指标的过滤、时间限定、衍生方式也是指标口径的一部分,应与方案保持一致。
dimensions 维度和日期粒度决定查询粒度;少维度查询需要指标支持上卷。
filters 筛选字段、表达式和筛选值必须能在物化表上表达。只筛选、不展示的字段同样会影响命中。
timeConstraint 限定 metric_time 的查询范围;需要落在已物化的数据范围内。
specialMvConfig 用于指定候选物化表及未命中处理策略,主要用于调试或已知目标物化表的场景。
resultFilters 通常否 在结果返回阶段筛选,不应用它替代需要在明细/物化数据上执行的 filters
orderslimitoffset 通常否 影响结果排序和返回行数;排序字段应存在于查询指标或维度中。

下面是一份可作为排查基线的完整请求。后续各节只展示与当前入参有关的部分:

{
  "metrics": ["order_count"],
  "dimensions": ["metric_time__day", "province"],
  "filters": ["IN([province],\"浙江\")"],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") >= \"2025-02-01\" AND DateTrunc([metric_time],\"DAY\") <= \"2025-02-28\"",
  "orders": [{"metric_time__day": "asc"}],
  "limit": 100
}

3. metrics:指标是否匹配

3.1 判断规则

查询中涉及的所有指标,必须全部包含在加速方案的指标列表中,或能由方案内已物化的辅助指标正确推导。

  • 少查指标:允许继续匹配;如同时省略了维度,还需要确认指标支持上卷。
  • 多查指标:只要有一个指标不在方案中且无法推导,该方案不能命中。
  • ⚠️ 复杂指标:平均值、去重、占比、同环比和复合指标不能默认按普通数值相加。只有方案保存了正确汇总所需的辅助数据,并支持相应上卷时才可能命中。

例如,方案已物化 order_countorder_amountrefund_amount

查询 metrics 是否可继续匹配 原因
["order_count"] 可以 查询指标是方案指标的子集。
["order_count", "order_amount"] 可以 两个指标均被方案覆盖。
["order_count", "delivery_amount"] 不可以 delivery_amount 未被方案覆盖。

3.2 metricDefinitions:带业务限定、时间限定或同环比的指标

当加速方案中的指标本身带有业务筛选、时间限定或同环比等衍生方式时,建议通过 metricDefinitions 定义查询指标。这样可以确保查询使用的指标口径与方案物化时一致。

原方案配置示意:

{
  "metrics": ["count_order_id_p_rq1gidwb23dvbxneadglx"],
  "metricDefinitions": {
    "count_order_id_p_rq1gidwb23dvbxneadglx": {
      "refMetric": "count_order_id_p",
      "filters": ["IN([sex],\"上海\")"],
      "period": "relative_date 0 day of 0 day",
      "metricGrain": "day",
      "indirections": ["sameperiod__year__value"]
    }
  }
}
字段 说明 对命中的影响
refMetric 引用平台中已定义的基础指标。 应与方案中的基础指标一致。
filters 指标自身的业务限定。 这是指标口径的一部分,不能用不等价的全局筛选替代。
period 指标的时间限定。 会影响实际计算日期范围。
metricGrain 时间限定使用的指标日期粒度。 应与方案及查询粒度兼容。
indirections 同环比、占比、排名等衍生方式。 需要方案支持相应的辅助指标和汇总方式。

可命中写法:方案物化“上海订单数”时,查询继续使用相同临时指标定义。

{
  "metrics": ["count_order_id_p_rq1gidwb23dvbxneadglx"],
  "metricDefinitions": {
    "count_order_id_p_rq1gidwb23dvbxneadglx": {
      "refMetric": "count_order_id_p",
      "filters": ["IN([sex],\"上海\")"],
      "period": "relative_date 0 day of 0 day",
      "metricGrain": "day"
    }
  },
  "dimensions": ["metric_time__day"]
}

不能按该方案命中的写法:改查基础指标,并以不等价的筛选临时替代指标定义。

{
  "metrics": ["count_order_id_p"],
  "filters": ["IN([sex],\"北京\")"],
  "dimensions": ["metric_time__day"]
}

4. dimensions:维度、日期粒度与上卷

4.1 基础规则

在不使用维度扩展时,查询维度应由方案维度覆盖。

  • ✅ 查询维度比物化维度少:仅在被省略维度允许上卷时可以命中。
  • ❌ 查询新增方案未覆盖的维度:不能按基础规则命中。
  • ❌ 查询粒度比物化粒度更细:不能由该方案完整回答。

例如,方案按“日期(日)、城市、门店”物化:

查询 dimensions 结果
["metric_time__day", "city", "store"] 与方案粒度相同,可以继续匹配。
["metric_time__day", "city"] 若指标允许按 store 上卷,可以命中。
["metric_time__day", "city", "channel"] channel 未被覆盖,不能按基础规则命中。
["metric_time__hour", "city"] 比日粒度更细,不能命中日粒度方案。

4.2 日期维度

日期维度需要使用“日期维度 __ 粒度”的统一格式,例如 dt__monthmetric_time__day。支持的粒度以实际维度配置为准。

原方案配置示意:

{
  "dimensions": ["dt__month"]
}

以下示例保留原有业务场景:方案使用 dt__month,临时指标为“上海订单数”。

可命中示例:查询维度保持为 dt__month

{
  "metrics": ["count_order_id_p_rq1gidwb23dvbxneadglx"],
  "metricDefinitions": {
    "count_order_id_p_rq1gidwb23dvbxneadglx": {
      "refMetric": "count_order_id_p",
      "filters": ["IN([sex],\"上海\")"],
      "period": "relative_date 0 day of 0 day",
      "metricGrain": "day"
    }
  },
  "dimensions": ["dt__month"],
  "filters": [
    "DateTrunc([dt],\"DAY\") = \"2025-02-02\"",
    "IN([shop_name],\"百事\")"
  ]
}

不能命中示例:将日期维度改为未带粒度标识的 dt。这会改变查询维度标识,无法按原方案匹配。

{
  "metrics": ["count_order_id_p_rq1gidwb23dvbxneadglx"],
  "metricDefinitions": {
    "count_order_id_p_rq1gidwb23dvbxneadglx": {
      "refMetric": "count_order_id_p",
      "filters": ["IN([sex],\"上海\")"],
      "period": "relative_date 0 day of 0 day",
      "metricGrain": "day"
    }
  },
  "dimensions": ["dt"],
  "filters": [
    "DateTrunc([dt],\"DAY\") = \"2025-02-02\"",
    "IN([shop_name],\"百事\")"
  ]
}

4.3 维度扩展与多表命中概览

“查询维度必须是方案维度子集”是单表直接命中的基础规则。当前版本在单表无法完整回答查询时,还会依次尝试:

  1. 单表直接匹配:一张物化表同时覆盖查询指标、维度、筛选和时间范围。
  2. 维度扩展匹配:物化表保存关联键,查询时补齐物化表中未保存的维度。
  3. 多表物化匹配:用多张可用物化表分别回答不同指标或数据域,再合并结果。

维度扩展和多表命中不是对任何查询的兜底。它们仍需保证每一条参与改写的数据路径都能正确表达查询维度、筛选和时间范围;最终以查询记录中的实际命中物化表为准。

4.4 维度扩展:在不重建物化表的前提下补齐维度

维度扩展适合“指标和核心粒度稳定,但分析维度经常变化”的场景。物化表不必保存每个展示维度,而是保存可以回关联的业务键;查询时系统通过数据模型关系补齐目标维度并重新汇总。

命中前提

条件 说明
存在关联键 物化表至少要保留一个可关联到目标维度的键,例如用户 ID、商品 ID、门店 ID 或机构 ID。
关系路径可用 从物化表中的关联键到目标维度存在已配置、可用且语义明确的关系路径。
指标可再次汇总 补齐维度后需要按新维度重新汇总,指标必须允许该汇总方式。
目标维度可补齐 当前适用于可直接关联的原始字段;复杂计算字段、表达式维度通常不能通过维度扩展补齐。
时间和筛选仍可执行 timeConstraintfilters 不能超出物化结果及其扩展路径的可表达范围。

场景一:按用户属性补齐分析维度(单一路径)

业务关系:订单事实表可通过 user_id 关联用户维表,用户维表中有 user_levelcity

物化方案保存的内容 查询希望得到的内容 是否可尝试维度扩展
metric_time__dayuser_idorder_amount metric_time__dayuser_levelcityorder_amount 可以。系统可通过 user_id 补齐用户等级和城市,再按查询维度汇总。

原有模型关系示意:

查询请求示例:

{
  "metrics": ["order_amount"],
  "dimensions": ["metric_time__day", "user_level", "city"],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") >= \"2025-02-01\" AND DateTrunc([metric_time],\"DAY\") <= \"2025-02-28\""
}

这个请求在基础规则下新增了 user_levelcity,单表直接匹配可能失败;若方案保留 user_id、关系路径可用且 order_amount 可重新汇总,则可通过维度扩展命中。

场景二:同一类维度通过不同业务路径补齐

同一个“地区”字段可能具有不同业务语义。例如交易既关联开户机构,也关联交易机构:

物化方案保存的内容 查询维度 扩展路径
user_idtrade_org_idtrade_amount account_open_regiontrade_org_region user_id → 开户机构 → 开户地区trade_org_id → 交易机构 → 交易机构地区

原有模型关系示意:

{
  "metrics": ["trade_amount"],
  "dimensions": ["account_open_region", "trade_org_region"]
}

这类查询的关键不是两个维度名称是否都叫“地区”,而是每个维度是否已绑定到正确的业务路径。若路径缺失、被误配为同一路径,或关系无法唯一确定,系统不会为了命中而猜测业务语义。

场景三:新增维度也用于筛选

维度扩展不仅可用于展示维度,也可用于筛选字段。仍以用户扩展为例:

{
  "metrics": ["order_amount"],
  "dimensions": ["metric_time__day", "user_level"],
  "filters": ["IN([city],\"上海\",\"杭州\")"]
}

city 可由物化表保留的 user_id 关联得到,且该路径与 user_level 使用的路径一致或可同时成立,则可以尝试维度扩展。反之,city 虽未展示但无法补齐时,查询仍不能命中。

不适用或容易失败的场景

场景 原因 建议
物化表没有用户 ID、商品 ID 等关联键 无法从物化结果关联到目标维度。 将高频扩展所需的业务键加入方案,或直接将目标维度物化。
查询的是明细、不可上卷或强依赖唯一行语义的指标 补维后重新汇总可能改变结果。 使用更细粒度方案或普通查询。
目标维度是复杂表达式或计算字段 当前无法稳定映射到物化表及关系路径。 将表达式结果作为方案内维度物化,或使用普通查询。
用户维度发生一对多映射 补维会放大事实记录,无法保证指标口径。 先治理关系模型,确保关联语义和基数正确。

4.5 多表命中:由多张物化表共同回答查询

多表命中适合“同一次查询的指标分布在不同物化方案中,但这些方案能够以相同查询粒度共同回答结果”的场景。它不会把任意一张实时明细表与物化表拼接,而是要求参与改写的相关数据均有可用物化结果。

命中前提

条件 说明
指标并集覆盖 候选物化表中的指标并集必须覆盖本次 metrics 的全部指标。
维度兼容 每张参与物化表都要能表达查询的分组维度和筛选维度,或自身满足维度扩展条件。
范围与筛选可用 每张参与表都要通过各自的时间范围、过滤条件和指标口径校验。
物化数据齐全 相关表均需有可用物化结果;暂不支持“部分指标走物化、部分指标实时直查”的混合命中。
合并语义一致 参与表需能按相同的查询粒度合并,避免重复汇总或关联放大。

系统会先召回候选物化表,检查候选表的指标并集是否覆盖查询指标,再验证每张表的维度、筛选与时间范围,最后选择可覆盖全部指标的表组合。因此,一张表“看起来有部分指标”并不等于一定会参与最终命中。

场景一:指标分布在两张物化表

假设存在两张已成功更新、时间范围相同的物化表:

物化表 已物化指标 已物化维度
mv_order order_countorder_amount metric_time__dayprovincechannel
mv_refund refund_countrefund_amount metric_time__dayprovincechannel

查询同时需要订单和退款指标:

{
  "metrics": ["order_amount", "refund_amount"],
  "dimensions": ["metric_time__day", "province"],
  "filters": ["IN([channel],\"线上\")"],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") >= \"2025-02-01\" AND DateTrunc([metric_time],\"DAY\") <= \"2025-02-28\""
}

可以尝试多表命中的原因是:

  • mv_order 覆盖 order_amountmv_refund 覆盖 refund_amount,两者指标并集覆盖全部查询指标;
  • 两张表均能表达 metric_time__dayprovince 和筛选字段 channel
  • 两张表的数据范围都覆盖 2025 年 2 月。

场景二:筛选字段未展示,但每张表都必须支持

在上一个场景中,channel 没有出现在 dimensions,但它会影响每个指标的结果。以下配置不能保证多表命中:

物化表 指标 维度
mv_order order_amount metric_time__dayprovincechannel
mv_refund refund_amount metric_time__dayprovince

请求仍为:

{
  "metrics": ["order_amount", "refund_amount"],
  "dimensions": ["metric_time__day", "province"],
  "filters": ["IN([channel],\"线上\")"]
}

mv_refund 无法在物化结果上执行 channel 筛选。即使 mv_order 可以命中,两张表也不能共同正确回答这次查询,系统会放弃这组多表物化结果。

场景三:时间范围不一致

物化表 数据范围
mv_order 2025-02-012025-02-28
mv_refund 2025-02-012025-02-25
{
  "metrics": ["order_amount", "refund_amount"],
  "dimensions": ["metric_time__day"],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") >= \"2025-02-01\" AND DateTrunc([metric_time],\"DAY\") <= \"2025-02-28\""
}

虽然两张表的指标和维度都匹配,但 mv_refund 的数据范围不能覆盖 2 月 26 日至 28 日。系统不能用一张物化表补全、再让另一张表实时直查,因此该查询不能命中这组多表物化结果。

场景四:部分指标没有物化结果

{
  "metrics": ["order_amount", "refund_amount", "delivery_amount"],
  "dimensions": ["metric_time__day", "province"]
}

若只有 mv_ordermv_refunddelivery_amount 没有任何可用物化表,则候选物化表的指标并集无法覆盖全部查询指标。当前能力不会让订单和退款使用物化、运费实时计算后再拼接;本次查询会回退普通查询,或由其他完整方案处理。

场景五:单表优先,不要依赖固定选表顺序

若一张方案已同时覆盖 order_amountrefund_amount 及全部查询维度,系统会优先尝试单表改写。多表命中主要用于没有任何一张单表能完整回答查询的情况。

如果多张候选物化表均可覆盖同一指标,最终选表还会受方案优先级、实际维度兼容性、时间范围和筛选校验影响。不要在业务逻辑中假设系统一定选择某张指定表;如需验证指定表,请使用 specialMvConfig.hints 并谨慎设置 penetrateOnMiss

多表命中排查清单

  1. 列出本次 metrics,确认候选物化表的指标并集是否覆盖全部指标。
  2. dimensionsfilters 中使用的字段合并成清单,逐张确认候选物化表均能表达这些字段,或具备有效维度扩展路径。
  3. 对每张候选表确认已上线、刷新成功,且数据范围覆盖相同的 timeConstraint
  4. 确认参与表之间的关联和聚合粒度一致;避免一张表为明细级、另一张表为汇总级后直接合并。
  5. 在查询记录中查看最终命中的物化表列表;若只命中一张或没有命中,按指标、维度、筛选、时间范围逐项排除。

5. filters:筛选条件是否可被加速支持

筛选条件不仅影响展示结果,也影响能否安全地使用物化数据。需要同时检查全局 filtersmetricDefinitions.filters 以及物化方案内的筛选条件。

以下情况通常会导致基础规则下无法命中:

  • 使用加速方案未覆盖的字段进行筛选;
  • 将物化可识别的原始字段改写为无法映射的复杂表达式后再筛选;
  • 只在筛选中出现、但方案无法表达的维度;
  • 用与方案内筛选不等价的条件替换已固化的指标口径。

5.1 按已配置日期维度筛选

假设加速方案已使用 dt__daymetric_time__day 作为日期维度:

{
  "dimensions": ["dt__day", "metric_time__day"]
}

筛选应继续使用方案已配置的日期字段和对应粒度。推荐写法如下:

{
  "filters": [
    "DateTrunc([dt],\"DAY\") = DateTrunc(\"2025-02-02\",\"DAY\")"
  ]
}
{
  "filters": [
    "DateTrunc([metric_time],\"DAY\") = DateTrunc(\"2025-02-02\",\"DAY\")"
  ]
}

5.2 字段间日期比较

原方案中的维度匹配示意:

对于字段间日期比较,建议使用方案创建或平台生成的规范表达式,保持字段、粒度和函数结构一致:

{
  "filters": [
    "(DATETRUNC(['metric_time'], \"DAY\")) = (DATETRUNC(['open_date'], \"DAY\"))"
  ]
}

不要因为表达式看起来相近就自行替换日期粒度或函数结构。以下写法在原场景中无法映射到物化方案:

{
  "filters": [
    "DATETRUNC(['metric_time'], \"day\") = DATETRUNC(['open_date'], \"DAY\")"
  ]
}

5.3 与方案筛选保持口径一致

原方案已添加门店筛选条件的示意:

可命中写法:使用与方案相同的筛选语义。

{
  "filters": ["IN([shop_name],\"百事\")"]
}

不能按该方案命中的写法:将方案筛选替换为另一种表达式。即使业务含义看似接近,也不应假设它一定能被改写。

{
  "filters": ["[shop_name] = \"百事\""]
}

提示:只用于筛选而未出现在 dimensions 中的字段同样会影响命中。若希望查询按“一级类目”展示、按“三级类目”筛选,则“三级类目”也必须能被物化方案表达,或满足已启用的维度扩展条件。

6. timeConstraint:时间范围与最新可用日期

timeConstraint 用于限定 metric_time 的查询时间范围。查询范围应落在物化表已生成的数据范围内;创建或回补方案后,请先确认物化表最近一次更新成功。

假设加速方案已回补 2025-01-012025-12-10 的数据:

查询时间范围 是否可按覆盖原则命中 原因
2025-12-012025-12-10 可以 查询范围完全被已物化数据覆盖。
2025-12-11 不可以 查询日期超出已确认的可用范围。
2025-12-012025-12-11 不应依赖命中 结束日期超出已确认的可用范围。
2024-12-12 不可以 查询日期早于已物化范围。

日粒度查询示例:

{
  "dimensions": ["metric_time__day"],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") >= \"2025-12-01\" AND DateTrunc([metric_time],\"DAY\") <= \"2025-12-10\""
}

月粒度方案应使用月粒度的查询维度和筛选;不能要求月粒度物化表回答按日或按小时的更细查询:

{
  "dimensions": ["metric_time__month"],
  "timeConstraint": "DateTrunc([metric_time],\"MONTH\") = DateTrunc(\"2025-12-01\",\"MONTH\")"
}

系统会按物化分区粒度对齐时间范围,并结合方案运行状态处理最后一个已更新分区。不要把该实现细节理解为“未来日期一定可命中”;生产查询以物化表实际数据范围和查询记录为准。

7. specialMvConfig:指定物化表

specialMvConfig 可指定本次查询优先尝试的物化表,以及指定物化表未命中时是否允许回退普通查询。它适合调试、压测或已明确知道目标物化表的场景,不建议作为绕过常规命中校验的方式。

字段 类型 说明
hints 数组 指定候选物化表名称,支持多个。
penetrateOnMiss 布尔 true:指定物化未命中时回退普通查询;false:未命中时直接返回失败。
{
  "metrics": ["order_count"],
  "dimensions": ["metric_time__day"],
  "filters": [],
  "timeConstraint": "DateTrunc([metric_time],\"DAY\") = \"2025-12-10\"",
  "specialMvConfig": {
    "hints": ["split_mv_1015"],
    "penetrateOnMiss": false
  },
  "queryResultType": "SQL_AND_DATA"
}

hints 不为空时,指定物化表会优先参与改写;请自行确认它已上线、包含所需指标和维度,并且真实数据范围足以回答查询。penetrateOnMiss: false 会把未命中转为查询失败,生产使用前应充分验证。

8. 推荐排查顺序

未命中时,按以下顺序排查通常最高效:

  1. 确认请求未关闭结果加速,物化方案已发布上线。
  2. 在物化表或方案详情中确认最近一次更新成功,且数据范围覆盖 timeConstraint
  3. 对照 metricsmetricDefinitions,检查指标、业务限定、时间限定及衍生方式是否与方案一致。
  4. 对照 dimensions、隐藏维度和日期粒度;少维度查询检查上卷能力,额外维度检查维度扩展的关联键和关系路径。
  5. 逐项核对 filters、指标内筛选和方案筛选,尤其是只筛选不展示的字段、层级下级字段和表达式筛选。
  6. 如使用 specialMvConfig,检查 hints 中的物化表名称、版本和数据可用性;再确认 penetrateOnMiss 是否符合预期。
  7. 在查询记录中查看实际命中的物化表。多表查询需要确认参与查询的各表都有可用物化结果。