Oceanbase查询优化:访问路径代价估算

概述

在生成执行计划之前,Oceanbase会估算访问路径的代价以剪除代价较大的访问路径,为进一步优化提供基础。

基本原理

在Oceanbase中,主要涉及以下几种路径的代价估算:

  • 基表访问路径

  • 连接路径

  • 子查询路径(不作介绍)

基表访问路径

根据访问方式的不同,基表访问主要可以分为GET操作和SCAN操作。根据查询使用的索引情况,上述两种方式各自需要考虑回表和不回表两种场景,下面依次进行说明。

GET操作
  • 回表场景下,GET操作的基表访问代价可以用如下公式表示:

cost = base_cost (二级索引访问代价)+ ib_cost(主索引访问代价) + network_cost(回表数据网络传输代价)

其中各部分的计算方式如下:

base_cost = io_cost (io代价)+ cpu_cost(cpu代价)

io_cost = MICRO_BLOCK_RND_COST(宏块读取代价常量) * num_micro_blocks_read(需要读取的宏块数) + FETCH_ROW_RND_COST(数据取回代价常量) * row_count(读取的行记录数)

cpu_cost = (CPU_TUPLE_COST(单记录处理代价常量) + PROJECT_COLUMN_RND_COST (列投影代价常量)* column_count(列数)) * row_count (读取的行记录数)+ qual_cost(谓词代价)

ib_cost = io_cost + cpu_cost

network_cost = DEFAULT_NETWORK_PER_BYTE_COST(网络传输代价常量) * (average_row_size_(平均行记录大小) * row_count (传输的行记录数)* column_count(列数)) / table_column_count_(表的列数)

  • 不回表场景下,GET操作的基表访问代价可以用如下公式表示:

cost = base_cost(主索引访问代价)

SCAN操作
  • 回表场景下,SCAN操作的基表访问代价可以用如下公式表示:

cost = base_cost (二级索引访问代价)+ ib_cost(主索引访问代价) + network_cost(回表数据网络传输代价)

其中各部分的计算方式如下:

base_cost = io_cost (io代价)+ cpu_cost(cpu代价)

io_cost = num_micro_blocks_read(需要读取的微块数) * MICRO_BLOCK_SEQ_COST(微块顺序读取代价常量)

cpu_cost = row_count(读取的行记录数) * CPU_TUPLE_COST(单记录处理代价常量)+ project_cost (投影代价)+ qual_cost(谓词代价)

project_cost = (PROJECT_COLUMN_SEQ_COST(投影列顺序处理代价常量) * column_count(列数)) * row_count(读取的行记录数)

  • 不回表场景下,SCAN操作的基表访问代价可以用如下公式表示:

cost = base_cost(主索引访问代价)

连接路径

根据连接方式的不同,优化器会使用不同的逻辑进行代价估算:

Merge Join

op_cost = CPU_TUPLE_COST(单记录处理代价常量) * (left_rows(左表记录数) + right_rows(右表记录数)) + qual_cost(谓词代价) + join_cost(连接代价)

其中各部分的计算方式如下:

join_cost = JOIN_PER_ROW_COST (单记录连接代价常量)* out_tuples(输出记录数)

out_tuples = cond_tuples(满足连接条件的记录数) * filter_selectivity(过滤条件选择率)

cond_tuples = cart_tuples(左右表笛卡尔积的记录数) * cond_selectivity(连接条件选择率)

Hash Join

op_cost = CPU_TUPLE_COST (单记录处理代价常量)* (left_rows(左表记录数) + right_rows(右表记录数)) + material_cost(左表物化代价) + build_cost(hash表构建代价) + probe_cost (hash表probe代价)+ qual_cost (谓词代价)+ join_cost(连接代价)

其中各部分的计算方式如下:

build_cost = BUILD_HASH_PER_ROW_COST(单记录hash表插入代价常量) * left_rows(左表记录数)

probe_cost = PROBE_HASH_PER_ROW_COST (单记录hash表probe代价常量)* right_rows(右表记录数)

join_cost = JOIN_PER_ROW_COST (单记录连接代价常量)* out_tuples(输出记录数)

cond_tuples = left_rows(左表记录数) * right_rows(右表记录数) * cond_sel(连接条件选择率)

Nestloop Join

op_cost = left_rows(左表记录数) * once_rescan_cost(内循环代价) + qual_cost(谓词代价) + join_cost(连接代价)

其中各部分的计算方式如下:

once_rescan_cost = right_cost_(右表代价) + right_rows(右表记录数) *CPU_TUPLE_COST(单记录处理代价常量)

join_cost = JOIN_PER_ROW_COST(单记录连接代价常量) * out_tuples(输出记录数)

out_tuples = cart_tuples (左右表笛卡尔积的记录数)* filter_selectivity(过滤条件选择率)

代码解析

基表访问路径的代价估算逻辑入口为ObOptEstCost::cost_table_one_batch,执行逻辑如下:

  1. 调用cost_table_get_one_batch函数对GET操作的访问代价进行估算。

  1. 调用cost_table_scan_one_batch函数对SCAN操作的访问代价进行估算。

连接路径的代价估算逻辑根据连接方式的不同,分别位于ObOptEstCost::cost_mergejoinObOptEstCost::cost_hashjoinObOptEstCost::cost_nestloop

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值