Skip to content

# Issue:FieldQueryCache 不支持 Value::BigUint #359

Description

@wensiwei12

Issue:FieldQueryCache 不支持 Value::BigUint

问题类型

  • 类型:Bug / 性能问题
  • 组件:wp-knowledge
  • 影响版本:0.16.0
  • 影响场景:OML 使用 ip_to_biguint 进行 IP 数值转换后执行 SQL 查询

问题描述

当前 wp-knowledge 0.16.0 中的 FieldQueryCache 仅支持以下参数类型:

  • Value::Chars
  • Value::Digit
  • Value::IpAddr

不支持 Value::BigUint

OML 的 ip_to_biguint 会生成 Value::BigUint。因此,使用转换结果作为 SQL 参数时,即使查询参数和查询结果完全相同,本地字段查询缓存也无法命中。

复现方式

OML 规则示例:

__sip_ip_num = pipe @__sip | ip_to_biguint;

__sip_country_code, __sip_country_name = select country_iso_code, country_name
from geo.ip_geo
where start_ip_num <= @__sip_ip_num
  and end_ip_num >= @__sip_ip_num
order by start_ip_num desc
limit 1;

连续发送相同 IP,使 @__sip_ip_num 每次生成相同的 BigUint 值。

实际行为

FieldQueryCache 的本地索引逻辑没有处理 Value::BigUint,该类型会落入默认分支:

_ => None

结果如下:

  1. 查询前无法通过 BigUint 参数查找本地缓存。
  2. 查询完成后无法使用 BigUint 参数保存本地缓存索引。
  3. 后续相同查询持续发生本地缓存 miss。

预期行为

对于相同的 SQL、相同的参数类型以及相同的 BigUint 参数值:

  1. 第一次查询访问 provider 并写入本地缓存。
  2. 后续查询命中 FieldQueryCache
  3. 后续查询不再重复访问 PostgreSQL provider。

性能影响

当前 IP 查询压测结果:

  • PostgreSQL 单独执行真实 IP 查询:平均约 0.010 ms,串行 QPS 约 97,179
  • 整体 OML 规则关闭全局结果缓存:吞吐仅为几千级。
  • 开启全局结果缓存:吞吐提升到约 2 万级

这说明全局结果缓存已经生效,但 BigUint 查询仍无法使用 FieldQueryCache 本地缓存。

为什么全局缓存开启后仍然会变快

当前系统存在两层缓存:

  1. FieldQueryCache:OML 查询使用的本地字段缓存,目前不支持 BigUint
  2. 全局 SQL 结果缓存:缓存完整 SQL 查询结果,支持 BigUint 参数哈希。

因此,即使本地缓存 miss,开启全局结果缓存后仍可能走以下路径:

OML 查询
  -> FieldQueryCache miss
  -> 全局 SQL 结果缓存 hit
  -> 直接返回缓存结果

关闭全局结果缓存时,路径变为:

OML 查询
  -> FieldQueryCache miss
  -> PostgreSQL 查询
  -> 结果转换与字段拷贝

全局缓存命中可以绕过连接池获取、网络通信、PostgreSQL 执行、结果读取和部分 provider 开销,因此即使没有修复 BigUint 的 local cache,enabled = true 仍然会明显提升性能。

根因

FieldQueryCache 的参数索引逻辑未覆盖 Value::BigUint

  • get_idx 不支持 BigUint
  • try_up_idx 不支持 BigUint
  • 索引达到上限重置时没有清理 BigUint 索引。

修复建议

FieldQueryCache 增加独立的 BigUint 索引,例如:

biguint_idx: HashMap<String, usize>

并在以下位置增加 Value::BigUint 处理:

  • get_idx
  • try_up_idx
  • 本地索引重置逻辑

建议使用规范化十进制字符串或 BigUint 本身作为索引键,并保持类型隔离,避免以下两个值发生冲突:

Value::Chars("1")
Value::BigUint(1)

验收标准

  • 相同 BigUint 参数可以命中本地缓存。
  • 不同 BigUint 参数不会发生缓存碰撞。
  • CharsDigitIpAddrBigUint 之间不会发生缓存碰撞。
  • 本地索引达到重置阈值后,BigUint 索引也会被清理。
  • provider generation 变化时,缓存失效行为保持不变。
  • 增加单参数和多参数 BigUint 查询的单元测试。
  • 开启全局结果缓存和关闭全局结果缓存时,缓存命中统计符合预期。

相关说明

当前 PostgreSQL 的 IP 查询执行计划和索引正常,问题重点不在 PostgreSQL 索引,而在 OML 查询链路中的缓存分层以及 BigUint 类型支持不完整。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions