分区表中的索引


【 使用环境 】生产环境
【 OB or 其他组件 】
【 使用版本 】
【问题描述】分区表下有 id 全局查询,
【复现路径】
1 id、和 create_time 作为联合主键,以create_time 进行分区

partition by range columns(create_time)
(partition p_history values less than (‘2026-04-01 00:00:00’),
2 create_time 在左侧

PRIMARY KEY (create_time, id),

3 当前有 where id查询,explain 走了 全表扫描了。

SELECT
  COUNT(*) AS total
FROM
  book_record_info
WHERE
  (id = ?)

============================================================================
|ID|OPERATOR                     |NAME               |EST.ROWS|EST.TIME(us)|
----------------------------------------------------------------------------
|0 |SCALAR GROUP BY              |                   |1       |13445326    |
|1 |└─PX COORDINATOR             |                   |1       |13445326    |
|2 |  └─EXCHANGE OUT DISTR       |:EX10000           |1       |13445326    |
|3 |    └─MERGE GROUP BY         |                   |1       |13445325    |
|4 |      └─PX PARTITION ITERATOR|                   |2       |13445325    |
|5 |        └─TABLE FULL SCAN    |book_recor_info|2       |13445325    |
============================================================================
Outputs & filters:
-------------------------------------
  0 - output([T_FUN_COUNT_SUM(T_FUN_COUNT_SUM(T_FUN_COUNT(*)))]), filter(nil), rowset=16
      group(nil), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT_SUM(T_FUN_COUNT(*)))])
  1 - output([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=16
  2 - output([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=16
      dop=1
  3 - output([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=16
      group(nil), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT(*))])
  4 - output([T_FUN_COUNT(*)]), filter(nil), rowset=16
      force partition granule
  5 - output([T_FUN_COUNT(*)]), filter([book_recor_info.id = demote_cast('2080501958866344416', BIGINT(20, 0))]), rowset=16
      access([book_recor_info.id]), partitions(p[0-16])
      is_index_back=false, is_global_index=false, filter_before_indexback[false], 
      range_key([book_recor_info.create_time], [book_recor_info.id]), range(MIN,MIN ; MAX,MAX)always true, 
      pushdown_aggregation([T_FUN_COUNT(*)])

问题:
如何优化,
1 创建 local还是 glable 的 id索引 ?
2 还是业务上避免 id 查询?
@论坛小助手

8 个赞

针对您的问题,首先需要了解的是,在 OceanBase 中对于分区表使用联合主键进行查询时,如果查询条件没有包含分区键(这里是 create_time),则可能会导致全表扫描的情况。创建合适的索引可以帮助优化这种情况,但具体的解决方案依赖于您的业务场景和数据访问模式。

建议的 obdiag 日志采集

虽然您遇到的问题可能直接通过优化SQL或者调整索引设计来解决,但如果想要更深入地分析性能问题或验证某些假设的话,可以使用 obdiag 来收集与当前问题相关的日志信息,特别是关于SQL执行效率方面的信息。

日志采集场景: SQL性能问题
日志采集命令:

obdiag gather scene run --scene=observer.perf_sql --env "{db_connect='-h<your_host> -P<your_port> -u<your_username>@<your_tenant> -p<your_password> -D<your_database>', trace_id='<your_trace_id>'}"

请将 <your_host><your_port><your_username><your_tenant><your_password><your_database> 替换成实际值,并选择一个适当的 trace_id 作为标识符。这条命令会帮助我们收集有关指定数据库连接下的SQL执行性能相关的信息,包括但不限于慢查询日志、执行计划等。

下一步行动建议

  1. 根据上述日志采集命令收集到的日志,尝试自行查看是否存在明显的性能瓶颈。
  2. 如果无法自行诊断,请将生成的日志文件压缩包提供给技术支持团队进一步分析。
  3. 考虑对 book_record_info 表基于 id 字段创建局部索引或全局索引来改善查询性能。具体哪种方式更适合取决于数据分布情况及查询频率等因素,请根据实际情况测试后再决定。
  4. 检查是否有其他高成本操作影响了整体性能,例如大量写入操作可能导致读取延迟增加。
  5. 尝试调整应用程序逻辑以利用现有索引结构,如尽可能结合 create_time 进行范围查询而非单独使用 id

需要您补充提供的信息:

为了更好地理解您的需求并给出更具针对性的建议,请回答以下几个问题:

  1. 是否已经存在基于 id 或其他列上的任何索引?如果有,请列出它们的具体定义。
  2. 当前执行的SQL语句是什么样子的?能否分享给我们用于分析?
  3. 对该表执行此查询的大致频率是多少?每次涉及的数据量大概有多少?
  4. 在执行这个查询之前或之后,系统上是否有其他的重负载任务运行?
  5. 此次查询所期望达到的最佳响应时间是多少?

希望以上内容能帮助您解决问题,如果还有其他疑问欢迎随时联系我们!

附上敏捷诊断工具 obdiag 使用帮助链接

3 个赞

学习学习

1 个赞

签到…

1 个赞

1 更新统计信息。
2 再给ID建一个索引。
3 速度不行就接受。
4 结合业务,改改SQL,比如加上create_time

2 个赞

查一下ob的版本号SHOW VARIABLES like ‘version_comment’;

1 个赞

OceanBase_CE 4.5.0.0 (r100000012025112711-0e8d5ad012baf0953b2032a35a88bdf8886e9a7a) (Built Nov 27 2025 12:05:51)

给ID建一个索引的话,建议是
局部普通索引 (Local)
还是
全局索引 (Global)
这个表的数据量很大,所以才做了分区。

另外现在SQL已经加了 create_time 了

id 加了索引解决了