在 OceanBase(MySQL 模式下),我有一张几个亿记录的大表,执行简单的 SELECT MIN(id) 或 SELECT MAX(id) 查询时,耗时非常长(将近10秒),而在同样配置的 Oracle 中只需要几百毫秒。从数据库内核的角度看,造成这种性能差异的可能原因是什么?除了调整超时时间,有没有更好的实践来优化这类聚合查询?
6 个赞
期待答复
1 个赞
把表改为分区表,建分区索引,加并行度等等,我是这么考虑的
2 个赞
试一下列存表效果如何
1 个赞
是否涉及分布式查询呢?
1 个赞
在 OceanBase 数据库中,大表的简单聚合查询性能较差的原因可能与执行计划的选择有关。具体来说,如果查询没有使用索引而选择了全表扫描,会导致大量的逻辑读取,显著增加查询时间。此外,优化器的统计信息不准确也可能导致执行计划选择不优。为了优化这类查询,您可以采取以下措施:
-
确保索引存在:检查表上的
id列是否有合适的索引。如果id列是主键或有唯一索引,通常会使用索引进行聚合查询。 -
收集统计信息:确保表的统计信息是最新的。可以使用
DBMS_STATS包来收集统计信息,例如:CALL DBMS_STATS.GATHER_TABLE_STATS('your_schema', 'your_table'); -
使用 Hint 强制索引:如果优化器没有选择最优的索引,可以使用 Hint 强制使用索引。例如:
SELECT /*+ INDEX(your_table your_index) */ MIN(id) FROM your_table; -
检查执行计划:使用
EXPLAIN语句查看查询的执行计划,确保查询使用了索引而不是全表扫描。例如:EXPLAIN SELECT MIN(id) FROM your_table; - 优化表结构:如果表的结构设计不合理,可能需要重新设计表结构,例如使用分区表来减少查询的数据量。
-
配置参数:确保数据库的配置参数适合大表查询,例如调整
ob_query_timeout以防止查询因超时而中断。
通过以上措施,可以显著提升大表聚合查询的性能。
检索到的文档如下:
1 个赞
对统计字段加索引啊.
用列存,向量化+SIMD(相当于批处理,你可以理解行存是一行行处理,串着的),而且列存压缩率,以及 所需的数据可能更集中(实际看你SQL怎么写的,例如只查单列,条件也只有这一列,那么相比于行存 IO会大大减少),列存还会在宏块/微块中 提前计算 min、max 这种聚合信息,这样只需要取这些聚合信息,而不需要重新对比(减少CPU计算),然后用败者树,做个最大/最小堆,这事就完成了,如果再采用 MOW 的方式,在增量数据库记录完整的行,那么部分算子可以分别 下推到 增量和基准数据(提前筛选所需数据,而不是增量和基准数据合并后,再计算,可以极大减少计算量)。
总结下上面用到的方法:
- 让所需的数据集中,节省IO(列存);
- 让单核CPU并行,提高单核cpu计算能力(向量化+SIMD);
- 提前计算(列存会提前计算一些 聚合类的数值,如:max、min等);
- 算子下推(MOW);
Oracle 的话,是堆表,我估计用到了3 (I guess)。