oracle where 条件执行顺序。

三味书屋 2010-12-20 02:05:52
select* from temp where a = 1 and b = 2 and c= 3 and d= 4 ;
想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。
...全文
8017 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
oceanhunter 2011-01-13
  • 打赏
  • 举报
回复
能淘汰最多数据的条件排在最后。
oceanhunter 2011-01-13
  • 打赏
  • 举报
回复
orcale 是倒序解析执行的。
etsilence 2011-01-13
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 tuies 的回复:]
引用 39 楼 etsilence 的回复:
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,……
[/Quote]

好吧,你自己都说了,优化器都不知道a=5和b=6应该先执行哪个,那你凭什么知道呢?
在a=1 and b=2 and c=3 这种绝对平衡的where条件中(所谓绝对平衡是指数据分布,返回结果,执行方式等效率全部一样),CBO怎么执行的,有必要去考虑吗,怎么执行的结果都一样。如果where条件不平衡,同样不用考虑先后顺序,因为CBO会把所有where条件平等看待,无所谓先后。
etsilence 2011-01-12
  • 打赏
  • 举报
回复
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面,它都会首先执行.
tuies 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 etsilence 的回复:]
oracle 10g以后的版本就不要考虑where条件的执行顺序了,毫无意义,你当优化器是傻的啊,连按什么顺序执行最快都不知道.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面……
[/Quote]

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

就lz的提问而言,我们假设的条件是a.b.c.d这四个条件都是一样的,都不会走索引,也就是在进行全表扫描的情况下而比较的,I/O成本已不再考虑范围内。讨论这个最主要的作用在于使用短路原则,减少CPU进行比较的次数,其并不会减少I/O的产生,当然在大多数情况下,根据大数吃小数的原则,cpu的计算成本相比较I/O是微乎其微的.
另外我的测试虽然样本不足,但就选定的样本而言也是经过多次测试(不下于40次)的比较才得到的结果,至少可以可以看出oracle在这个样本方面所选用的算法
tuies 2011-01-11
  • 打赏
  • 举报
回复
顺便说下,我做的测试环境为 oracle10g
tuies 2011-01-11
  • 打赏
  • 举报
回复
建表;
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好一点



mer1234567 2011-01-10
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 cuishengmin 的回复:]
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的……
[/Quote]
正解
lxyzxq2008 2011-01-05
  • 打赏
  • 举报
回复
这个问题提的真好啊~,有没有甲骨文的人出来给证实下?
hyde100 2011-01-05
  • 打赏
  • 举报
回复
Oracle优化器会根据最优的执行计划自动调整执行顺序
cuishengmin 2011-01-05
  • 打赏
  • 举报
回复
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。
wangjingjing0428 2010-12-27
  • 打赏
  • 举报
回复
应该是从 是d 往 a 这边执行的,因为感觉每次出现报错都是从后往前报错的呢
ohfox 2010-12-26
  • 打赏
  • 举报
回复
10g R2貌似没有RBO了.
感觉应该根据自己对表数据的理解,加ordered提示
erlei20082008 2010-12-26
  • 打赏
  • 举报
回复
可以明确的告诉你,SQl语句是从右往左执行的,如果有子查询,也会先做子查询,所以为了提高查询效率,尽量把精确条件往后写,我们做的项目表数据有的数据量达到10几亿,还有点建议,就是尽量不要用*,因为它会调用数据字典,增加查询成本。
Jiangli7810 2010-12-25
  • 打赏
  • 举报
回复
从右向左
huangdh12 2010-12-24
  • 打赏
  • 举报
回复
从后往前执行的
iqlife 2010-12-24
  • 打赏
  • 举报
回复
执行肯定是右往左,
Leshami 2010-12-24
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 randy_ideal 的回复:]
解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了
[/Quote]
应该看看执行计划
lijinsheng2010 2010-12-24
  • 打赏
  • 举报
回复
这个与解释器的规则有关,比如基于成本规则的,where 后面的条件是从下往上执行,也就是最后的先执行。
feixianxxx 2010-12-24
  • 打赏
  • 举报
回复
我想10g的优化器 会帮你搞定这些位置的吧。。
cbo模式下?
加载更多回复(21)

3,491

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧