概述:

对于数据严重倾斜的,极端如以下例子,不同的传入值,可能执行计划不同,制定执行计划时,就要求知道变量的值。对于绑定变量的情况,我们知道Oracle 有 _optim_peek_user_binds 参数,控制是否启用变量窥探。KingbaseES 也有类似参数,控制是否启用变量窥探。

窥探机制

KingbaseES 采用以下判断机制,决定是否固定执行计划:

  • 前5次执行时,每次都会根据实际传入的实际绑定变量新生成执行计划进行执行,即每次都是硬解析,同时会记录这5次的执行计划;

  • 当第6次开始执行时,会生成一个通用的执行计划(generic plan),同时与前5次的执行计划进行比较,如果比较的结果是通用执行计划不比前5次的执行计划差,以后就会把这个通用的执行计划固定下来,这之后即使传入的值发生变化后,执行计划也不再变化。这就相当于Oracle打开了绑定变量窥视的功能。

  • 当然,当第6次开始执行时,如果通用的执行计划(generic plan)比前5次的某一个执行计划差,则以后则每次都重新生成执行计划,即以后永远都是硬解析了。

构建例子

1、构建测试数据

create table t1(id integer,name text);
insert into t1 select 1,repeat('a',100) from generate_series(1,1000000);
insert into t1 select 2,repeat('b',100) ;
create index ind_t1_id on t1(id);
analyze t1;
prepare t1_plan(integer) AS select count(*) from t1 where id=$1;

2、测试窥探机制

测试一:

test=# prepare t1_plan(integer) AS select * from t1 where id=$1;
PREPARE
test=#
test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = $1)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = $1)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = $1)
(2 rows)

结论:可以看到,第6次执行时,变为 id=$1,说明执行计划变成通用执行计划了。后续,即使传入的 值是 2,也不会走索引。

测试二:

test=# prepare t1_plan(integer) AS select * from t1 where id=$1;
PREPARE
test=# explain execute t1_plan(2);
QUERY PLAN
----------------------------------------------------------------------
Index Scan using ind_t1_id on t1 (cost=0.42..4.44 rows=1 width=105)
Index Cond: (id = 2)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
----------------------------------------------------------------------
Index Scan using ind_t1_id on t1 (cost=0.42..4.44 rows=1 width=105)
Index Cond: (id = 2)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
----------------------------------------------------------------------
Index Scan using ind_t1_id on t1 (cost=0.42..4.44 rows=1 width=105)
Index Cond: (id = 2)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
----------------------------------------------------------------------
Index Scan using ind_t1_id on t1 (cost=0.42..4.44 rows=1 width=105)
Index Cond: (id = 2)
(2 rows) test=# explain execute t1_plan(2);
QUERY PLAN
----------------------------------------------------------------------
Index Scan using ind_t1_id on t1 (cost=0.42..4.44 rows=1 width=105)
Index Cond: (id = 2)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows) test=# explain execute t1_plan(1);
QUERY PLAN
--------------------------------------------------------------
Seq Scan on t1 (cost=0.00..29742.01 rows=1000001 width=105)
Filter: (id = 1)
(2 rows)

结论:如果第6次与前5次执行计划是不一致的,后续都不会走通用的执行计划。本例中,哪怕后续连续超过 5次 传入同一值,都不会固定执行计划。

3、窥探机制问题

与Oracle 相比,KES需要前 5 次执行绑定变量的SQL,都会窥探变量值,只有在执行计划都一致时,第6次执行时才会固定执行计划。可以看到,这种机制相比于Oracle,出现执行计划错误的概率更低,但是还是有一定的几率。为了解决该问题,KingbaseES提供参数,可以关闭变量窥探机制。

plan_cache_mode 参数控制是否固定执行计划(执行计划共享),还是永远进行硬解析。可以取以下三个值:

  • auto: 默认值,即根据以上的机制选择是否固定执行计划。
  • force_custom_plan: 关闭绑定变量窥视,永远进行硬解析。
  • force_generic_plan: 走通用的固定执行计划(generic plan)

注意:与Oracle 实例级的执行计划共享不同,KingbaseES 只支持会话级执行计划共享。

KingbaseES 绑定变量窥探机制的更多相关文章

  1. PostgreSQL 绑定变量窥探

    今天我们要探讨的是 custom执行计划和通用执行计划.这一技术在 Oracle中被称为绑定变量窥视.但 Kingbase中并没有这样的定义,更严格地说,Kingbase叫做custom执行计划和通用 ...

  2. KingbaseES 绑定变量与游标共享

    对于重复执行的SQL,需要使用绑定变量,避免SQL的重复解析.但是,并不是说使用了绑定变量,就一定能避免硬解析.具体可以参见:https://www.cnblogs.com/kingbase/p/16 ...

  3. ORACLE绑定变量隐式转换导致性能问题

    年后一次系统升级后,监控数据库的工具DPA发现数据库的Total Wait时间突然飙增,如下截图所示,数据库的总体等待时间对比升级前飙增了非常多 另外就是发现出现了较多的等待事件,主要有latch: ...

  4. Oracle ACS 绑定变量窥视 条件

    1. ACS简介 Oracle Database 11g提供了Adaptive Cursor Sharing (ACS)功能,以克服以往不该共享的游标被共享的可能性.ACS使用两个新指标:sensit ...

  5. Oracle 课程九之绑定变量

    课程目标 完成本课程的学习后,您应该能够: •变量绑定的目的 •父子游标 •游标共享 •绑定窥探 •SQL语句处理流程 •硬解析.软解析.软软解析 •变量绑定的应用场景   1.游标 游标可以理解为S ...

  6. Oracle面对“数据倾斜列使用绑定变量”场景的解决方案

    1.背景知识介绍 2.构造测试用例 3.场景测试 4.总结 1.背景知识介绍     我们知道,Oracle在传统的OLTP(在线事务处理)类系统中,强烈推荐使用绑定变量,这样可以有效的减少硬解析从而 ...

  7. PL/SQL 训练12--动态sql和绑定变量

    --什么是动态SQL?动态PL/SQL--动态SQL是指在运行时刻才构建执行的SQL语句--动态PL/SQL是指整个PL/SQL代码块都是动态构建,然后再编译执行 --动态SQL来可以用来干什么? - ...

  8. Oracle --获取绑定变量的值.

    SELECT * FROM DBA_HIST_SQLBIND WHERE SNAP_ID>67073 AND SNAP_ID<=67079 AND SQL_ID='3DR3410F086P ...

  9. 使用EXECUTE IMMEDIATE来生成含有绑定变量的SQL

    一个SQL,通过SPM固定它的执行计划,可以通过DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE实现.也可以通地此功能在不修改原SQL的情况下对其加HINT来固定执行计划.D ...

随机推荐

  1. SAP Web Dynpro - 个性化和配置

    根据业务需求,您可以实现许多标准应用程序,并且Web Dynpro应用程序的UI可以根据要求而有所不同. 应用配置 要配置Web Dynpro应用程序,首先要为单个Web Dynpro组件配置数据记录 ...

  2. Obsidian基础教程

    Obsidian基础教程 相关链接 2021年新教程 - Obsidian中文教程 - Obsidian Publish 软通达 基础设置篇 1. 开启实时预览 开启实时预览模式,所见即所得 打开设置 ...

  3. wcf .net webService和 .net webApi的联系与差异

    首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...

  4. RPA应用场景-自动轮询汇总报表

    场景概述 自动轮询汇总报表 所涉系统名称 券商披露网站 人工操作(时间/次) 36小时 所涉人工数量 1 操作频率 每月 场景流程 1.每月初机器人自动登录网站轮询36家券商披露的财务报告,并下载 2 ...

  5. sql server2016 数据库日志 清空语句

    /*1.查询数据库日志文件名称*/--TC_MES_DEV为数据库名--这里的 数据库日志名,可以用以下注释的语句进行查询(_log那个)USE [TC_MES_DEV]GOSELECT file_i ...

  6. Unity3D学习笔记4——创建Mesh高级接口

    目录 1. 概述 2. 详论 3. 其他 4. 参考 1. 概述 在文章Unity3D学习笔记2--绘制一个带纹理的面中使用代码的方式创建了一个Mesh,不过这套接口在Unity中被称为简单接口.与其 ...

  7. MyBatis 映射文件

    Mybatis映射文件简介 1) MyBatis 的真正强大在于它的映射语句.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉 ...

  8. SpringBoot之MongoDB附件操作

    前言 近期自己针对附件上传进一步学习,为了弥足项目中文件上传的漏洞,保证文件上传功能的健壮性和可用性,现在我将自己在这一块的心得总结如下: 一.pom.xml依赖的引入 <dependency& ...

  9. 2022宁波市第五届网络安全大赛MISC方向部分wp

    BlackAndWhite 1. 得到了三百多张黑白颜色的图片,将白色图片转为数字0,黑色图片转为数字1,得到二进制字符串 01100110011011000110000101100111011110 ...

  10. 运行Flutter时连接超时

    这个墙不知道浪费了开发者多少的时间!!!!!!!!!!!!!!!!!!! 1.修改仓库地址为阿里仓库: 编辑android/build.gradle,把文件中的两处: google() jcenter ...