对于某一条 SQL 的某一种执行计划,默认情况下 OceanBase 数据库只会保留一个计划,该计划由第一次执行 SQL 时生成;但在某些情况下,同一条 SQL 的参数值可能会影响到计划的选择,计划缓存可能会根据需要,为不同的参数值保留不同的执行计划,从而保证每次执行时可以使用最合适的计划。OceanBase 数据库支持自适应计划共享(Adaptive Cursor Sharing)功能支持不同参数条件下的计划选择。
计划缓存是一个典型的 Key-Value 结构,Key 就是参数化后的 SQL 字符串,Value 就是该条 SQL 所对应的执行计划。在 OceanBase 数据库的计划缓存中,SQL 的执行计划可以分为本地计划、远程计划和分布式计划三种类型。在计划缓存中,同一条 SQL 根据其需要访问的数据不同,可能同时具有三种执行计划。
计划缓存的淘汰
计划缓存的淘汰是指将执行计划从计划缓存中删除,减少计划缓存对内存的使用,OceanBase 数据库支持自动淘汰和手动淘汰两种方式。
自动淘汰
自动淘汰是指当计划缓存占用的内存达到了需要淘汰计划的内存上限(即淘汰计划的高水位线)时,对计划缓存中执行计划自动进行淘汰。
自动淘汰示例如下:
如果租户内存大小为 10G, ob_plan_cache_percentage=10, ob_plan_cache_evict_high_percentage=90, ob_plan_cache_evict_low_percentage=50,则计划缓存内存上限绝对值 = 10G * 10 / 100 = 1G,淘汰计划的高水位线 = 1G * 90 / 100 = 0.9G,淘汰计划的低水位线 = 1G * 50 / 100 = 0.5G。当该租户在某个 server 上计划缓存使用超过 0.9G 时,会触发淘汰,优先淘汰最久没执行的计划,当淘汰到使用内存只有 0.5G 时,则停止淘汰。如果淘汰速度没有新计划生成速度快,计划缓存使用内存达到内存上限绝对值 1G 时,将不再往计划缓存中添加新计划,直到淘汰后使用的内存小于 1G 才会添加新计划到计划缓存中。
手动淘汰
手动淘汰是指强制将计划缓存中计划进行删除,现在支持指定不同租户对应的当前服务器或全部服务器中计划缓存全部删除,具体命令如下:
其中 tenant_list 和 global 为可选字段:
- 如果 tenant_list 没有指定,则清空所有租户的计划缓存,否则只清空特定租户的。
- 如果 global 没有指定,则清空本机的计划缓存,否则清空该租户所在的所有server上的计划缓存。
- SQL 中涉及的表的 SCHEMA 进行变更时(比如添加索引,删除或增加列等),该 SQL 对应的在计划缓存中的执行计划将刷新。
- SQL 进行 outline 计划绑定变更时,该 SQL 对应的执行计划会刷新,更新为按绑定的 outline 生成的执行计划。
计划缓存的使用控制
是否使用计划缓存可以使用系统变量及 hint 进行控制。
控制方式 | 解释 |
系统变量控制 | ob_enable_plan_cache 设置为 ture 时表示 SQL 请求可以使用计划缓存,设置为 false 时表示 SQL 请求不使用计划缓存。可进行 session 级和 global 级设置,默认使用该设置为 true。 |
Hint 控制 |
- 内存大小超过 20M 执行计划不加入计划缓存。
- 如果该计划为分布式计划且涉及多个表,则不加入计划缓存。
计划缓存的视图
执行计划相关视图包括:
- (g)v$plan_cache_stat:记录每个计划缓存的状态,每个计划缓存在该视图中有一条记录。
- (g)v$plan_cache_plan_stat:记录计划缓存中所有 plan 的具体信息及每个计划总的执行统计信息, 每个 plan 在该视图中一条记录。