oracle的optimizer会对一些sql语句进行查询转换,比如:

  1. 合并视图
  2. 子查询非嵌套化
  3. inlist转换

下面讲讲遇到的in list转化优化的案例:

create table test(
col1 varchar2(12)
col2 number
ext varchar2(4000)
); create index test_ind on test(user_id, col2);
create sequence seq_test cache 200;

第一步:准备一些测试数据(10个线程随机的插入数据):

#!/bin/sh
for((i=1;i<=$1;i++))
do
/home/oracle/insert.sh &
done
#######################################################
#!/bin/sh
. /home/oracle/.bash_profile
sqlplus -S /nolog<<EOF
conn test/ali88
declare
type arraylist is table of varchar2(20 byte);
arr_user arraylist;
ran number;
begin
arr_user := arraylist();arr_user.extend(3);arr_user(1):='xpchild001';
arr_user(2):='xpchild002';arr_user(3):='xpchild003';
ran :=dbms_random.value(1,3);
while(1>0) loop
insert into test(col1,col2,ext)values(arr_user(ran),seq_test.nextval,dbms_random.string('|', 300));
commit;
DBMS_LOCK.SLEEP(0.05);
end loop;
end;
/
EOF

下面看这个语句的执行计划:

  

delete from test t where col1 =:1 and col2 in
( :2 , :3 , :4 , :5 , :6 , :7 , :8 , :9 , :10 , :11 , :12 , :13 , :14 , :15 , :16 , :17 , :18 , :19 , :20 , :21); --------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 948 | 5 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| test | 4 | 948 | 5 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | test_ind | 4 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("col1"=:1)
filter("col2"=TO_NUMBER(:2) OR "col2"=TO_NUMBER(:3) OR
.........
"col2"=TO_NUMBER(:21))

分析:对于test_ind(col1,col2)这样的组合索引,oracle的优化器使用了access+filter的扫描方式,而对于热点表,或者col1存在大量记录的时候,
这样的扫描会从col1找到最小的col2,顺着leaf节点的链表,找到col2的最大值的区间里,进行filter,看下autotrace后的结果:

  

Statistics
----------------------------------------------------------
12389 consistent gets
20 rows

这里扫描了col1=:1前导列的所有leaf块,所以尽管只有20条记录,却有12389的逻辑读。

下面对这个sql进行inlist的查询转换:

  

ops$admin@orcl>alter session set optimizer_index_caching=100;

delete /*+ use_concat*/from test t where col1 =:1 and col2 in
( :2 , :3 , :4 , :5 , :6 , :7 , :8 , :9 , :10 , :11 , :12 , :13 , :14 , :15 , :16 , :17 , :18 , :19 , :20 , :21); ---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 948 | 3 (0)| 00:00:01 |
| 1 | INLIST ITERATOR | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| test | 4 | 948 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | test_ind | 4 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("col1"=:1 AND ("col2"=TO_NUMBER(:2) OR "col2"=TO_NUMBER(:3) OR
"col2"=TO_NUMBER(:4) OR "col2"=TO_NUMBER(:5) OR "col2"=TO_NUMBER(:6) OR
......
/*+
BEGIN_OUTLINE_DATA
NUM_INDEX_KEYS(@"DEL$1" "T"@"DEL$1" "test_ind" 2)
INDEX(@"DEL$1" "T"@"DEL$1" ("test"."col1"
"test"."col2"))
OUTLINE_LEAF(@"DEL$1")
ALL_ROWS
OPT_PARAM('optimizer_index_caching' 100)
OPT_PARAM('_gby_hash_aggregation_enabled' 'false')
OPT_PARAM('_optim_peek_user_binds' 'false')
OPT_PARAM('_index_join_enabled' 'false')
OPT_PARAM('query_rewrite_enabled' 'false')
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

注意:oracle的优化器会对in 列表的查询转换为or的查询,使用use_concat的hint提示,使oracle可以把or的操作转化为concatenate的union all操作。
但是这里如果想要转化为inlist的eterator操作,必须还要调整optimizer_index_caching,可以在system或者session级别,optimizer_index_caching的值的范围
是0到100,表示的是百分比,这个参数影响oracle优化器在选择index时的cost计算,这里设置成100,表示扫描过的root,branch节点块都cache在buffer里,所以每次
iterate从root到branch再到leaf节点时,oracle优化器认为cost会比较小,倾向于使用inlist iterator。

看一下autotrace后的结果:

Statistics
----------------------------------------------------------
81 consistent gets
20 rows

即每条记录平均三个逻辑读,从root->branch->leaf->table block。

  如果在生产环境中可以使用profile来固定上面的执行计划,这样不用更改任何的代码逻辑:

  

declare
v_hints sys.sqlprof_attr;
sql_fulltext clob;
begin
select SQL_FULLTEXT
into sql_fulltext
from v$sqlarea
where sql_id = 'xxxxxx';
v_hints := sys.sqlprof_attr('NUM_INDEX_KEYS(@"DEL$1" "T"@"DEL$1" "test_ind" 2)',
'INDEX(@"DEL$1" "T"@"DEL$1" ("test"."col1"',
'"test"."col2"))',
'OUTLINE_LEAF(@"DEL$1")',
'ALL_ROWS',
'OPT_PARAM(''optimizer_index_caching'' 100)');
dbms_sqltune.import_sql_profile(sql_fulltext,
v_hints,
'test',
force_match => true);
end;
/

  

oracle查询转换_inlist转换的更多相关文章

  1. Oracle中使用游标转换数据表中指定字段内容格式(拼音转数字)

    应用场景:将数据表TB_USER中字段NNDP的内容中为[sannanyinv]转换为[3男1女] 主要脚本:一个游标脚本+分割字符串函数+拼音转数字脚本 操作步骤如下: 1.创建类型 create ...

  2. ORACLE常用数值函数、转换函数、字符串函数介绍

    ORACLE常用数值函数.转换函数.字符串函数介绍. 数值函数: abs(m) m的绝对值 mod(m,n) m被n除后的余数 power(m,n) m的n次方 round(m[,n]) m四舍五入至 ...

  3. sql server 导出的datetime结果 CAST(0x00009E0E0095524F AS DateTime) 如何向mysql,oracle等数据库进行转换

    1. 处理 sql server 导出的 datetime 类型的字段 在进行sql server向mysql等其他数据进行迁移数据时,会发现使用sql server导出的datetime类型的结果是 ...

  4. hibernate查询部分字段转换成实体bean

    //hibernate查询部分字段转换成实体bean /** * 查询线路信息 */ @Override public List<Line> getSimpleLineListByTj(M ...

  5. 怎么将oracle的sql文件转换成mysql的sql文件

    怎么将sql文件导入PowerDesigner中的方法(将oracle的sql文件转换成mysql的sql文件)呢? 怎么将xx.sql文件的数据库结构导入powerdesigner 的方法呢? 现讲 ...

  6. LINQ查询表达式详解(2)——查询表达式的转换

    简介 C#在执行LINQ查询表达式的时候,并不会指定其执行语义,而是将查询表达式转换为遵循查询表达式模式的方法的调用.具体而言,查询表达式将转换为以下名称的调用:Where.Select.Select ...

  7. 45 个非常有用的 Oracle 查询语句

    ​ 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 Oracle 开发者都必备的技能,所以快 ...

  8. 40多个非常有用的Oracle 查询语句

    给大家介绍是40多个非常有用的Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有Oracle 开发者都必备的技能,所以快快收藏吧! 日期 ...

  9. 45个非常有用的 Oracle 查询语句小结

    45个非常有用的 Oracle 查询语句小结 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询.这些是所有 ...

随机推荐

  1. 双程动态规划 nyoj61

    题目大意: 在矩阵m*n中,从(1,1)点到(m,n)点,再从(m,n)点到(1,1)点,所走路线经过的同学最大好心值, 要求每个点只能走一遍. 分析: ①我们可以把它只看成两个人同时从(1,1)点, ...

  2. JDBC中事务的使用

    http://blog.sina.com.cn/s/blog_6f3ca78f01010pmj.html 当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对 ...

  3. javascript 获取url参数

    /** window.location.search获取url地址?以后的值 获取url参数有两种方法,第一种如下,第二种是通过正则 */ //基本版 function getParam() { va ...

  4. JSP EL表达式详细介绍

    一.JSP EL语言定义 E L(Expression Language)  目的:为了使JSP写起来更加简单. 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 ...

  5. 如何在Angular2中使用Forms

    在Angular2中形成两个基本对象是Control和ControlGroup. 控制用户输入 Control 一个控制表示一个输入字段(ngFormControl) 一个控制可以绑定到一个input ...

  6. Codevs 1138 聪明的质监员 2011年NOIP全国联赛提高组

    1138 聪明的质监员 2011年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 小 T 是一名质量监督员, ...

  7. 暑假集训(1)第二弹 -----Catch the cow(Poj3278)

    Description Farmer John has been informed of the location of a fugitive cow and wants to catch her i ...

  8. skip跳跃表的实现

    skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...

  9. Service Reference

    1 Add Web Reference    根据wsdl文件,按照老的asp.net webservice客户访问机制,生成webservice代理类的方法,即从System.Web.Service ...

  10. windows phone 扫描二维码

    在网上找了找扫描二维码的例子,利用ZXing库实现(下载),提供的Silverlight版本的下载,在网上搜了一下已经有wp的dll可用了,不过网上实现的条码扫描的例子还都是用的Silverlight ...