查询优化与调试

UModel PaaS接口提供了丰富的调试和优化工具,帮助开发者快速定位问题、优化查询性能并确保系统稳定运行。

应用案例

当前应用案例相关素材,请参考:umodel.zip

1. DryRun模式

1.1 DryRun概述

DryRun 模式是 UModel PaaS 接口的核心调试功能,允许预览查询生成的 SPL 而不实际执行,便于:

  • 查询预览:查看最终生成的 SPL 查询语句。

  • SPL验证:验证转换逻辑和字段映射是否正确。

  • 调试分析:快速定位转换过程中的问题。

  • 学习理解:理解 UModel 抽象到底层 SPL 的转换机制。

1.2 DryRun使用方法

基本语法

在任何UModel PaaS查询前添加DryRun设置:

.set "umodel_paas_mode"='dry_run';

-- 你的UModel PaaS查询

Phase 1 Table模式示例

.set "umodel_paas_mode"='dry_run';

.metric_set with(
    domain='apm', 
    name='apm.metric.apm.service', 
    source='metrics', 
    metric='request_count',
    query='service_id = "order-service"'
)

返回结果

.metricstore with(region='cn-hangzhou', project='cms-cms-umodel-paas-0620-kffw8bjagidkeyc2', metricstore='metricstore-apm') 
| prom-call promql_query_range('sum by (acs_arms_service_id) (rate(arms_app_requests_count_raw{acs_arms_service_id="order-service"}[1m]))', '1m')

Phase 2 Object模式示例

.set "umodel_paas_mode"='dry_run';

.entity_set with(domain='apm', name='apm.service', ids=['1ab40caaf6xa707e6'])
| entity-call get_golden_metrics()

返回结果

.let golden_metric_request_count_1=.metricstore with(project='proj-xtrace-xx-ap-southeast-3', metricstore='metricstore-apm-metrics') | prom-call promql_query_range('sum(sum_over_time_lcro(arms_app_requests_count_ign_destid_endpoint_parent_ppid_prpc_rpc{acs_arms_service_id="hwx28v3j7p@xx",callKind=~"http|rpc|custom_entry|server|consumer|schedule",service="payment"}[1m]))') | extend metric = 'request_count', metric_set_id = 'apm@metric_set@apm.metric.apm.service'; .let golden_metric_error_count_2=.metricstore with(project='proj-xtrace-xx-ap-southeast-3', metricstore='metricstore-apm-metrics') | prom-call promql_query_range('sum(sum_over_time_lcro(arms_app_requests_error_count_ign_destid_endpoint_parent_ppid_prpc_rpc{acs_arms_service_id="hwx28v3j7p@xx",callKind=~"http|rpc|custom_entry|server|consumer|schedule",service="payment"}[1m]))') | extend metric = 'error_count', metric_set_id = 'apm@metric_set@apm.metric.apm.service'; .let golden_metric_avg_request_latency_seconds_3=.metricstore with(project='proj-xtrace-xx-ap-southeast-3', metricstore='metricstore-apm-metrics') | prom-call promql_query_range('sum(sum_over_time_lcro(arms_app_requests_seconds_ign_destid_endpoint_parent_ppid_prpc_rpc{acs_arms_service_id="hwx28v3j7p@xx",callKind=~"http|rpc|custom_entry|server|consumer|schedule",service="payment"}[1m])) / sum(sum_over_time_lcro(arms_app_requests_count_ign_destid_endpoint_parent_ppid_prpc_rpc{acs_arms_service_id="hwx28v3j7p@xx",callKind=~"http|rpc|custom_entry|server|consumer|schedule",service="payment"}[1m]))') | extend metric = 'avg_request_latency_seconds', metric_set_id = 'apm@metric_set@apm.metric.apm.service'; $golden_metric_request_count_1 | union $golden_metric_error_count_2, $golden_metric_avg_request_latency_seconds_3

1.3 DryRun调试技巧

1.3.1 字段映射验证

通过DryRun检查字段映射是否正确:

.set "umodel_paas_mode"='dry_run';

-- 检查实体ID如何通过属性信息映射到存储字段
.entity_set with(domain='apm', name='apm.service', id=['1ab40caaf6xa707e6'])
| entity-call get_metric('apm', 'apm.metric.apm.service', 'request_count')

-- 检查实体查询字段如何映射到存储字段
.entity_set with(domain='apm', name='apm.service', query='service = "order-service"')
| entity-call get_metric('apm', 'apm.metric.apm.service', 'request_count')

观察返回的SPL中字段映射规则是否按预期应用。

1.3.2 过滤条件检查

验证复杂过滤条件的转换:

.set "umodel_paas_mode"='dry_run';

.entity_set with(domain='apm', name='apm.service', 
    query='service_id = "order-service" and region = "cn-hangzhou"')
| entity-call get_metric('apm', 'apm.metric.apm.service', 'request_count')

检查生成的SPL中过滤条件是否完整且正确。

1.3.3 关系查询调试

验证实体关系查询的字段映射:

.set "umodel_paas_mode"='dry_run';

.entity_set with(domain='apm', name='apm.service', query='service = "service-a"')
| entity-call get_relation_golden_metrics(
    'apm', 'apm.service', [], 'service = "service-b"',
    'calls', 'out', 'range', '5m')

检查源实体和目标实体的过滤条件是否正确组合。

1.4 DryRun最佳实践

  1. 逐步验证:从简单查询开始,逐步添加复杂条件。

  2. 对比验证:将 DryRun 结果与预期 SPL 对比。

  3. 字段检查:重点检查自定义字段的映射转换。

  4. 性能预估:通过生成的 SPL 评估查询复杂度。

2. 性能优化

2.1 查询计划优化

2.1.1 过滤条件优化

最佳实践:尽可能提供精确的过滤条件以减少数据扫描繁体,提升查询响应速度。

  • 注意: 如果是 phase2 模式,建议尽可能通过 ids 指定查询的实体ID,利用UModel能力进行查询转换。

.profile_set with(
    domain='apm', 
    name='apm.profile.cpu',
    query='service_id = "order-service" and profile_type = "cpu"'
)

.entity_set with(domain='apm', name='apm.service', id=['1ab40caaf6xa707e6'])
| entity-call get_metric('apm', 'apm.metric.apm.service', 'request_count')

2.1.2 指标模式步长设置

指标模式合理设置时间步长

  • 注意: 如无特殊必要,不建议手动设置步长,UModel 中内置的步长逻辑已经考虑了查询时间范围和数据量,能够自动选择合适的步长。

查询时间范围

推荐步长

说明

1小时内

1m

精确分析

1-6小时

3m

平衡精度与性能

6-24小时

5m

趋势分析

1-7

1h

长期趋势

7天以上

6h 或 1d

粗粒度分析

2.1.3 聚合策略优化

指标类查询尽可能优先使用聚合方式,否则可能会导致查询返回数据量过大,影响查询响应。

-- 推荐:使用聚合方式,如需获取特定维度,指定聚合维度

.metric_set with(
    domain='apm', 
    name='apm.metric.apm.service', 
    source='metrics', 
    metric='request_count',
    aggregate=true, -- 不指定维度,聚合所有指标成一条线
)

.metric_set with(
    domain='apm', 
    name='apm.metric.apm.service', 
    source='metrics', 
    metric='request_count',
    aggregate=true,
    aggregate_labels=['region']  -- 只聚合必要维度
)

-- 不推荐:不聚合,返回所有维度组合,数据量过大
.metric_set with(
    domain='apm', 
    name='apm.metric.apm.service', 
    source='metrics', 
    metric='request_count',
    aggregate=false  -- 返回所有维度组合
)

2.2 缓存策略

2.2.1 方法列表缓存

-- 缓存实体方法列表(相对稳定)
.entity_set with(domain='apm', name='apm.service')
| entity-call __list_method__()

缓存策略

  • 缓存时间:1-24小时。

  • 失效条件:UModel配置更新。

  • 适用场景:频繁的方法发现调用。

2.2.2 查询结果缓存

适合缓存的查询

-- 相对稳定的配置查询
.entity_set with(domain='apm', name='apm.service')
| entity-call list_data_set(['metric_set'], true)

-- 标签值查询(变化较少)
.entity_set with(domain='apm', name='apm.service')
| entity-call get_label_values('apm', 'apm.metric.apm.service', 'region')

缓存策略

  • 缓存时间:5-60分钟。

  • 失效条件:数据更新、配置变更。

  • 适用场景:高频重复查询。

3. 调试工具集

3.1 配置检查工具

-- 检查UModel配置完整性
.entity_set with(domain='apm', name='apm.service')
| entity-call __inspect__(
    check_data_sets=true,
    check_links=true,
    check_field_mappings=true,
    check_metrics=true
)

3.2 方法发现工具

-- 发现可用方法
.entity_set with(domain='apm', name='apm.service')
| entity-call __list_method__()

-- 发现关联数据集
.entity_set with(domain='apm', name='apm.service')
| entity-call list_data_set(['metric_set'], true)

-- 发现相关实体
.entity_set with(domain='apm', name='apm.service')
| entity-call list_related_entity_set(['contains'], 'out')

3.3 逐步调试流程

步骤1:验证基础配置

-- 1. 检查实体是否存在
.entity_set with(domain='apm', name='apm.service')
| entity-call get_entity_set()

-- 2. 检查关联数据集
.entity_set with(domain='apm', name='apm.service')
| entity-call list_data_set()

步骤2:测试简单查询

-- 3. 测试基础方法调用
.set "umodel_paas_mode"='dry_run';

.entity_set with(domain='apm', name='apm.service')
| entity-call __list_method__()

步骤3:逐步增加复杂度

-- 4. 添加过滤条件
.set "umodel_paas_mode"='dry_run';

.entity_set with(domain='apm', name='apm.service', query='service_id = "order-service"')
| entity-call get_golden_metrics()

-- 5. 测试关系查询
.entity_set with(domain='apm', name='apm.service', query='service_id = "order-service"')
| entity-call get_relation_golden_metrics('apm', 'apm.operation', [], '', 'contains', 'out')

4. 最佳实践总结

4.1 开发阶段

  • 先用DryRun:开发时优先使用DryRun验证查询逻辑。

  • 逐步构建:从简单查询开始,逐步增加复杂度。

  • 充分测试:测试边界条件和异常场景。

4.2 生产环境

  • 性能监控:持续监控查询性能指标。

  • 资源控制:合理设置并发限制和超时时间。

  • 缓存优化:充分利用查询结果缓存。

4.3 故障处理

  • 快速定位:使用DryRun和配置检查快速定位问题。

  • 日志分析:结合系统日志分析故障原因。

  • 分级处理:根据问题严重程度采用不同处理策略。