首批通过分布式安全可靠测评,为关键业务系统打造
执行计划缓存
更新时间:2023-10-27 11:31:07
执行计划缓存(Plan Cache)可以减少 SQL 执行计划的生成次数,提高查询性能。
OceanBase 数据库会缓存之前生成的执行计划,以便在下次执行该 SQL 时直接使用,可以避免反复执行,从而优化执行过程,这种策略被称为"Optimize Once",即"一次优化"。
计划缓存是一个典型的 Key-Value 结构,Key 就是参数化后的 SQL 字符串,Value 就是该条 SQL 所对应的执行计划。
每个租户在每一台服务器上都有一个独立的计划缓存,用以缓存在此服务器上处理过的 SQL 计划。在 OceanBase 数据库的计划缓存中,SQL 的执行计划可以分为本地计划、远程计划和分布式计划三种类型。在计划缓存中,同一条 SQL 根据其需要访问的数据不同,可能同时具有三种执行计划。
对于一条 SQL 的一种执行计划,OceanBase 数据库默认只会保留第一次执行 SQL 时生成的计划;但在某些情况下,同一条 SQL 的参数值可能会影响到执行计划的选择,所以计划缓存会根据需要,为不同的参数值保留不同的执行计划,从而保证每次执行时可以使用最合适的计划。
计划缓存的淘汰
计划缓存的淘汰是指将执行计划从计划缓存中删除,减少计划缓存对内存的使用。
OceanBase 数据库支持自动淘汰和手动淘汰两种方式。
自动淘汰
自动淘汰是指当计划缓存占用的内存达到了需要淘汰计划的内存上限(即淘汰计划的高水位线)时,对计划缓存中的计划执行自动淘汰。
触发执行计划淘汰的条件
每隔一段时间(具体时间间隔由配置项
plan_cache_evict_interval设置)系统会自动检查不同租户在不同服务器上的计划缓存,并判断是否需要执行计划淘汰。如果某个计划缓存占用的内存超过该租户设置的淘汰计划的高水位线,则会触发计划缓存淘汰。执行计划淘汰策略
当触发计划缓存淘汰后,优先淘汰最久没被使用的执行计划,淘汰一部分执行计划后,当计划缓存使用的内存为该租户设置的淘汰计划的低水位线时,停止淘汰。
与计划缓存淘汰相关配置
plan_cache_evict_interval该配置项用于设置检查执行计划是否需要淘汰的间隔时间。ob_plan_cache_percentage该系统变量用于设置计划缓存可使用内存占租户内存的百分比。公式如下: 计划缓存最多可使用内存(内存上限绝对值)=租户内存上限 * ob_plan_cache_percentage/100ob_plan_cache_evict_high_percentage该系统变量用于设置触发计划缓存淘汰的内存大小占内存上限绝对值的百分比。公式如下: 触发计划缓存淘汰的内存大小(淘汰计划的高水位线) = 内存上限绝对值 * ob_plan_cache_evict_high_percentage/100ob_plan_cache_evict_low_percentage该系统变量用于设置停止淘汰计划时的内存值(淘汰计划的低水位线) 。公式如下: 停止淘汰计划时的内存值(淘汰计划的低水位线)= 内存上限绝对值 * ob_plan_cache_evict_low_percentage/100
示例如下:
租户内存大小为 10 G,各参数值设置如下:
ob_plan_cache_percentage=10ob_plan_cache_evict_high_percentage=90ob_plan_cache_evict_low_percentage=50
则计算得出:
计划缓存内存上限绝对值=10G * 10/100=1 G
淘汰计划的高水位线=1G * 90/100=0.9 G
淘汰计划的低水位线=1G * 50/100=0.5 G
由计算结果可知,当该租户在某个服务器上计划缓存使用超过 0.9 G 时,会触发淘汰,优先淘汰最久没执行的计划,当淘汰到使用内存只有 0.5 G 时,则停止淘汰。 如果淘汰速度没有新计划生成速度快,计划缓存使用内存达到内存上限绝对值 1 G 时,将不在往计划缓存中添加新计划,直到执行淘汰后所占内存小于 1 G 才会添加新计划到计划缓存中。
手动淘汰
手动淘汰是指强制删除计划缓存中的计划。
OceanBase 数据库当前版本支持删除指定 Schema 和 SQL ID 的计划缓存,具体命令如下:
ALTER SYSTEM FLUSH PLAN CACHE [ [SQL_identifier] [database_list] tenant_list ] [global];
注意
Oracle 租户不支持细粒度的计划淘汰(即 SQL ID 级别的计划淘汰),只支持如下删除计划缓存命令:
ALTER SYSTEM FLUSH PLAN CACHE [global]。
参数解释如下:
SQL_identifier参数的格式为sql_id = 'xxx',用于指定 SQL。如果不指定该参数,表示清空所有 SQL 的计划缓存。database_list参数的格式为databases ='database_name, database_name...',用于指定 Schema。如果不指定该参数,表示清除所有计划缓存。MySQL 租户下,database_list是指 Database。tenant_list参数的格式为tenant = 'tenant_name, tenant_name....',用于指定租户范围。指定SQL_identifier和database_list参数时一定要指定tenant_list,将操作限定在租户范围内。说明
只有系统租户
sys才能指定tenant_list,其他租户不能指定该参数,即其他租户只能清除自己的计划缓存。如果系统租户不指定tenant_list则表示清除所有租户的计划缓存。global参数为可选字段。如果不指定该参数,表示清空本机的计划缓存。反之,则表示清空该租户所在的所有服务器上的计划缓存。
计划缓存的刷新
计划缓存中执行计划可能因为各种原因而失效,这时需要将计划缓存中失效计划进行刷新,即将该执行计划删除后重新优化生成计划再加入计划缓存。
如下场景会导致执行计划失效,需要对执行计划进行刷新:
SQL 中涉及表的 Schema 变更时(比如添加索引、删除或增加列等),该 SQL 在计划缓存中所对应的执行计划将被刷新。
SQL 中涉及重新收集表的统计信息时,该 SQL 在计划缓存中所对应的执行计划会被刷新。由于 OceanBase 数据库在数据合并时会统一进行统计信息的收集,因此在每次进行合并后,计划缓存中所有计划将被刷新。
计划缓存的使用控制
计划缓存可以使用系统变量及 Hint 实现使用控制。
系统变量控制
当
ob_enable_plan_cache设置为TURE时,表示 SQL 请求可以使用计划缓存;设置为FALSE时,表示 SQL 请求不使用计划缓存。默认为TURE。此系统变量可被设置为 Session 级别或者 Global 级别。Hint 控制
- 使用 Hint 语句
/*+ USE_PLAN_CACHE(NONE)*/表示不使用计划缓存。 - 使用 Hint 语句
/*+USE_PLAN_CACHE(DEFAULT)*/表示使用计划缓存。
- 使用 Hint 语句
计划缓存的视图
执行计划相关视图包括:
(g)v$plan_cache_stat记录每个计划缓存的状态,每个计划缓存在该视图中有一条记录。
(g)v$plan_cache_plan_stat记录计划缓存中所有执行计划的具体信息及每个计划总的执行统计信息。
(g)v$plan_cache_plan_explain记录某条 SQL 在计划缓存中的执行计划。
有关视图的详细参数信息,请参考 计划缓存相关视图。