oracle where 条件执行顺序。

时间:2022-02-09 22:18:43
select* from temp where a = 1 and b = 2 and c= 3 and  d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。

43 个解决方案

#1


是从d往a这边执行的吧。

#2


引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and  d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。

where条件从右往左解析。。

#3



------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符

#4


引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符


那怎么测试是正确的呢。

#5


有没有比较懂的人知道啊。

#6


解析顺序和执行顺序未必是一样的。从上边的实验看,解析 似乎是由左向右。
不知道oracle是否对and谓词执行顺序可以动态调整,如果是那样,就更无定论了。

#7


等待高手解释。。。。。。

#8


--解析都是从右往左解析的
scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON';
SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON'
                                        *
第 1 行出现错误:
ORA-00904: "LOCT": 标识符无效
--上面where条件的两个字段名都是错误的 提示loct无效

scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 AND LOC='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 AND LOC='BOSTON'
                         *
第 1 行出现错误:
ORA-00904: "DEPTNO1": 标识符无效
--上面where条件的loc字段是正确的 提示deptno1无效

scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOC='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOC='BOSTON'
                         *
第 1 行出现错误:
ORA-00904: "DEPTNO1": 标识符无效


scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOCA='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOCA='BOSTON'
                                       *
第 1 行出现错误:
ORA-00904: "LOCA": 标识符无效

#9


该回复于2010-12-20 17:45:49被版主删除

#10


Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾

按照这个说法 应该是 从右向左的

#11


知道了。。。thank you?

#12


引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符


这条应该没有编译过去就报错了吧。

#13


引用 8 楼 zhuomingwang 的回复:
SQL code
--解析都是从右往左解析的
scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON';
SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON'
                                        *
第 1 行出现……
这个实验详细,正解

#14


就是利用错误来检测解析顺序啊.
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
引用 12 楼 huaxianpeng 的回复:
引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
*
第 1 行出现错误:
ORA-00911: 无效字符


这……

#15


执行顺序应该是从右往左

#16


从右到左…

#17


语法检查和执行两回事。
解析顺序不一定是执行顺序。

#18


oracle 根据优化器的配置,自动进行调整!

#19


引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。


你应该说的是解析的顺序
从右到左

#20


引用 19 楼 wkc168 的回复:
引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。


你应该说的是解析的顺序
从右到左

sql92 是左到右  sql99右到左

都是把数据量大的过滤条件放到最后面(右)

#21


该回复于2010-12-21 13:05:27被版主删除

#22


从右到左…
如果表上有索引例如索引顺序( a,b,c) 

那么 尽量写成 where a =?  and b= ? and c= ? and d = ?

好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.

尽量把能过滤的大条件写在后面 如标志,男女等. 

#23


从后往前执行的

#24


解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了

#25


我想10g的优化器 会帮你搞定这些位置的吧。。
cbo模式下?

#26


这个与解释器的规则有关,比如基于成本规则的,where 后面的条件是从下往上执行,也就是最后的先执行。

#27


引用 24 楼 randy_ideal 的回复:
解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了

应该看看执行计划

#28


执行肯定是右往左,

#29


从右向左

#30


可以明确的告诉你,SQl语句是从右往左执行的,如果有子查询,也会先做子查询,所以为了提高查询效率,尽量把精确条件往后写,我们做的项目表数据有的数据量达到10几亿,还有点建议,就是尽量不要用*,因为它会调用数据字典,增加查询成本。

#31


10g R2貌似没有RBO了.
感觉应该根据自己对表数据的理解,加ordered提示

#32


应该是从 是d 往 a 这边执行的,因为感觉每次出现报错都是从后往前报错的呢

#33


楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。

#34


Oracle优化器会根据最优的执行计划自动调整执行顺序

#35


这个问题提的真好啊~,有没有甲骨文的人出来给证实下?

#36


引用 33 楼 cuishengmin 的回复:
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的……

正解

#37


建表;
create table t_testcolstart as select * from dba_objects; 
插入数据:
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;


SQL> select count(*) from t_testcolstart;

  COUNT(*)
----------
    807088
    
    
--目前表中以及包含近百万数据

--构造条件,测试数据

数据一: 
SQL> select * from t_testcolstart a where a.owner = 'HAHA' and a.object_name = 'HAHA';


已用时间:  00: 00: 00.06
SQL> select * from t_testcolstart a where a.object_name = 'HAHA'  and a.owner = 'HAHA';

已用时间:  00: 00: 00.07
SQL> select * from t_testcolstart a where a.owner = 'HAHA';


已用时间:  00: 00: 00.06
SQL> select * from t_testcolstart a where a.object_name = 'HAHA';


已用时间:  00: 00: 00.06

几乎看不出什么差距

测试二:
SQL> select * from t_testcolstart a where a.owner = 'HAHA'  and instr(a.object_name,'123') = 1;   b1


已用时间:  00: 00: 00.07
SQL> select * from t_testcolstart a where instr(a.object_name,'123') = 1   and a.owner = 'HAHA'; b2


已用时间:  00: 00: 00.06

SQL> select * from t_testcolstart a where instr(a.object_name,'123') = 1;                     b3


已用时间:  00: 00: 00.31

从本组数据我们可以看到 b1 与b2在查询的时候 都忽略了 instr(a.object_name,'123'), 不管其位与什么地方,都是先执行的 owner条件,
也就可以推出 oracle默认是先比较 干净的字段,后比较带函数的字段,并且实行了短路原则,只要第一个比较结果为否,后续都不会比较


测试三 

SQL> select * from t_testcolstart a where substr(a.object_type,2,4) = 'HAHA'  and instr(a.owner,'123') = 1; c1


已用时间:  00: 00: 00.29
SQL> select * from t_testcolstart a where instr(a.owner,'123') = 1   and substr(a.object_type,2,4) = 'HAHA'; c2


已用时间:  00: 00: 00.24
SQL> select * from t_testcolstart a where instr(a.owner,'123') = 1 ; c3


已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where substr(a.object_type,2,4) = 'HAHA'; c4
 

已用时间:  00: 00: 00.29

从本组数据 我们可以看到 c1与c4相差不多, c2与c3相差不多,也就可以推出 where 执行的过程是从左到右

测试四 为了验证结论三 ,再测试一组数据
SQL> select * from t_testcolstart a where substr(a.owner,2,4) = 'HAHA'  and instr(a.object_type,'123') = 1; d1

已用时间:  00: 00: 00.29
SQL> select * from t_testcolstart a where instr(a.object_type,'123') = 1   and substr(a.owner,2,4) = 'HAHA'; d2



已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where instr(a.object_type,'123') = 1 ; d3



已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where substr(a.owner,2,4) = 'HAHA'; d4



已用时间:  00: 00: 00.30

明显可以看出where执行条件是从左到右,并且可以看出instr 的效率要比substr好一点


    

#38


顺便说下,我做的测试环境为 oracle10g

#39


oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面,它都会首先执行.

#40


引用 39 楼 etsilence 的回复:
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面……


你以为优化器是万能的?请你告诉我 在比较 a = 5 与 b= 6 这个过程中 哪个成本最低?
CBO在计算成本的时候大多考虑的是I/O方面的,cpu方面的就比较少

就lz的提问而言,我们假设的条件是a.b.c.d这四个条件都是一样的,都不会走索引,也就是在进行全表扫描的情况下而比较的,I/O成本已不再考虑范围内。 讨论这个最主要的作用在于使用短路原则,减少CPU进行比较的次数,其并不会减少I/O的产生,当然在大多数情况下,根据大数吃小数的原则,cpu的计算成本相比较I/O是微乎其微的.
另外我的测试虽然样本不足,但就选定的样本而言也是经过多次测试(不下于40次)的比较才得到的结果,至少可以可以看出oracle在这个样本方面所选用的算法

#41


引用 40 楼 tuies 的回复:
引用 39 楼 etsilence 的回复:
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,……


好吧,你自己都说了,优化器都不知道a=5和b=6应该先执行哪个,那你凭什么知道呢?
在a=1 and b=2 and c=3 这种绝对平衡的where条件中(所谓绝对平衡是指数据分布,返回结果,执行方式等效率全部一样),CBO怎么执行的,有必要去考虑吗,怎么执行的结果都一样。如果where条件不平衡,同样不用考虑先后顺序,因为CBO会把所有where条件平等看待,无所谓先后。

#42


orcale 是倒序解析执行的。

#43


能淘汰最多数据的条件排在最后。

#1


是从d往a这边执行的吧。

#2


引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and  d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。

where条件从右往左解析。。

#3



------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符

#4


引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符


那怎么测试是正确的呢。

#5


有没有比较懂的人知道啊。

#6


解析顺序和执行顺序未必是一样的。从上边的实验看,解析 似乎是由左向右。
不知道oracle是否对and谓词执行顺序可以动态调整,如果是那样,就更无定论了。

#7


等待高手解释。。。。。。

#8


--解析都是从右往左解析的
scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON';
SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON'
                                        *
第 1 行出现错误:
ORA-00904: "LOCT": 标识符无效
--上面where条件的两个字段名都是错误的 提示loct无效

scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 AND LOC='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 AND LOC='BOSTON'
                         *
第 1 行出现错误:
ORA-00904: "DEPTNO1": 标识符无效
--上面where条件的loc字段是正确的 提示deptno1无效

scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOC='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOC='BOSTON'
                         *
第 1 行出现错误:
ORA-00904: "DEPTNO1": 标识符无效


scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOCA='BOSTON';
SELECT * FROM DEPT WHERE DEPTNO1=10 OR LOCA='BOSTON'
                                       *
第 1 行出现错误:
ORA-00904: "LOCA": 标识符无效

#9


该回复于2010-12-20 17:45:49被版主删除

#10


Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾

按照这个说法 应该是 从右向左的

#11


知道了。。。thank you?

#12


引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
                          *
第 1 行出现错误:
ORA-00911: 无效字符


这条应该没有编译过去就报错了吧。

#13


引用 8 楼 zhuomingwang 的回复:
SQL code
--解析都是从右往左解析的
scott@YPCOST> SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON';
SELECT * FROM DEPT WHERE DEPTNOQ=10 AND LOCT='BOSTON'
                                        *
第 1 行出现……
这个实验详细,正解

#14


就是利用错误来检测解析顺序啊.
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
引用 12 楼 huaxianpeng 的回复:
引用 3 楼 oraclefans_ 的回复:
SQL code

------测试了下,从左往右执行。。呵呵。
SQL> select * from dual where 1?=2 and 1=1 and 3?=2;
select * from dual where 1?=2 and 1=1 and 3?=2
*
第 1 行出现错误:
ORA-00911: 无效字符


这……

#15


执行顺序应该是从右往左

#16


从右到左…

#17


语法检查和执行两回事。
解析顺序不一定是执行顺序。

#18


oracle 根据优化器的配置,自动进行调整!

#19


引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。


你应该说的是解析的顺序
从右到左

#20


引用 19 楼 wkc168 的回复:
引用楼主 huaxianpeng 的回复:
select* from temp where a = 1 and b = 2 and c= 3 and d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。


你应该说的是解析的顺序
从右到左

sql92 是左到右  sql99右到左

都是把数据量大的过滤条件放到最后面(右)

#21


该回复于2010-12-21 13:05:27被版主删除

#22


从右到左…
如果表上有索引例如索引顺序( a,b,c) 

那么 尽量写成 where a =?  and b= ? and c= ? and d = ?

好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.

尽量把能过滤的大条件写在后面 如标志,男女等. 

#23


从后往前执行的

#24


解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了

#25


我想10g的优化器 会帮你搞定这些位置的吧。。
cbo模式下?

#26


这个与解释器的规则有关,比如基于成本规则的,where 后面的条件是从下往上执行,也就是最后的先执行。

#27


引用 24 楼 randy_ideal 的回复:
解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了

应该看看执行计划

#28


执行肯定是右往左,

#29


从右向左

#30


可以明确的告诉你,SQl语句是从右往左执行的,如果有子查询,也会先做子查询,所以为了提高查询效率,尽量把精确条件往后写,我们做的项目表数据有的数据量达到10几亿,还有点建议,就是尽量不要用*,因为它会调用数据字典,增加查询成本。

#31


10g R2貌似没有RBO了.
感觉应该根据自己对表数据的理解,加ordered提示

#32


应该是从 是d 往 a 这边执行的,因为感觉每次出现报错都是从后往前报错的呢

#33


楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。

#34


Oracle优化器会根据最优的执行计划自动调整执行顺序

#35


这个问题提的真好啊~,有没有甲骨文的人出来给证实下?

#36


引用 33 楼 cuishengmin 的回复:
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的……

正解

#37


建表;
create table t_testcolstart as select * from dba_objects; 
插入数据:
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;
insert into t_testcolstart select * from t_testcolstart;
commit;


SQL> select count(*) from t_testcolstart;

  COUNT(*)
----------
    807088
    
    
--目前表中以及包含近百万数据

--构造条件,测试数据

数据一: 
SQL> select * from t_testcolstart a where a.owner = 'HAHA' and a.object_name = 'HAHA';


已用时间:  00: 00: 00.06
SQL> select * from t_testcolstart a where a.object_name = 'HAHA'  and a.owner = 'HAHA';

已用时间:  00: 00: 00.07
SQL> select * from t_testcolstart a where a.owner = 'HAHA';


已用时间:  00: 00: 00.06
SQL> select * from t_testcolstart a where a.object_name = 'HAHA';


已用时间:  00: 00: 00.06

几乎看不出什么差距

测试二:
SQL> select * from t_testcolstart a where a.owner = 'HAHA'  and instr(a.object_name,'123') = 1;   b1


已用时间:  00: 00: 00.07
SQL> select * from t_testcolstart a where instr(a.object_name,'123') = 1   and a.owner = 'HAHA'; b2


已用时间:  00: 00: 00.06

SQL> select * from t_testcolstart a where instr(a.object_name,'123') = 1;                     b3


已用时间:  00: 00: 00.31

从本组数据我们可以看到 b1 与b2在查询的时候 都忽略了 instr(a.object_name,'123'), 不管其位与什么地方,都是先执行的 owner条件,
也就可以推出 oracle默认是先比较 干净的字段,后比较带函数的字段,并且实行了短路原则,只要第一个比较结果为否,后续都不会比较


测试三 

SQL> select * from t_testcolstart a where substr(a.object_type,2,4) = 'HAHA'  and instr(a.owner,'123') = 1; c1


已用时间:  00: 00: 00.29
SQL> select * from t_testcolstart a where instr(a.owner,'123') = 1   and substr(a.object_type,2,4) = 'HAHA'; c2


已用时间:  00: 00: 00.24
SQL> select * from t_testcolstart a where instr(a.owner,'123') = 1 ; c3


已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where substr(a.object_type,2,4) = 'HAHA'; c4
 

已用时间:  00: 00: 00.29

从本组数据 我们可以看到 c1与c4相差不多, c2与c3相差不多,也就可以推出 where 执行的过程是从左到右

测试四 为了验证结论三 ,再测试一组数据
SQL> select * from t_testcolstart a where substr(a.owner,2,4) = 'HAHA'  and instr(a.object_type,'123') = 1; d1

已用时间:  00: 00: 00.29
SQL> select * from t_testcolstart a where instr(a.object_type,'123') = 1   and substr(a.owner,2,4) = 'HAHA'; d2



已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where instr(a.object_type,'123') = 1 ; d3



已用时间:  00: 00: 00.23
SQL> select * from t_testcolstart a where substr(a.owner,2,4) = 'HAHA'; d4



已用时间:  00: 00: 00.30

明显可以看出where执行条件是从左到右,并且可以看出instr 的效率要比substr好一点


    

#38


顺便说下,我做的测试环境为 oracle10g

#39


oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面,它都会首先执行.

#40


引用 39 楼 etsilence 的回复:
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面……


你以为优化器是万能的?请你告诉我 在比较 a = 5 与 b= 6 这个过程中 哪个成本最低?
CBO在计算成本的时候大多考虑的是I/O方面的,cpu方面的就比较少

就lz的提问而言,我们假设的条件是a.b.c.d这四个条件都是一样的,都不会走索引,也就是在进行全表扫描的情况下而比较的,I/O成本已不再考虑范围内。 讨论这个最主要的作用在于使用短路原则,减少CPU进行比较的次数,其并不会减少I/O的产生,当然在大多数情况下,根据大数吃小数的原则,cpu的计算成本相比较I/O是微乎其微的.
另外我的测试虽然样本不足,但就选定的样本而言也是经过多次测试(不下于40次)的比较才得到的结果,至少可以可以看出oracle在这个样本方面所选用的算法

#41


引用 40 楼 tuies 的回复:
引用 39 楼 etsilence 的回复:
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,……


好吧,你自己都说了,优化器都不知道a=5和b=6应该先执行哪个,那你凭什么知道呢?
在a=1 and b=2 and c=3 这种绝对平衡的where条件中(所谓绝对平衡是指数据分布,返回结果,执行方式等效率全部一样),CBO怎么执行的,有必要去考虑吗,怎么执行的结果都一样。如果where条件不平衡,同样不用考虑先后顺序,因为CBO会把所有where条件平等看待,无所谓先后。

#42


orcale 是倒序解析执行的。

#43


能淘汰最多数据的条件排在最后。