想知道where 是从 a 往 d 执行的,还是d 往 a 这边执行的。
43 个解决方案
#1
是从d往a这边执行的吧。
#2
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
那怎么测试是正确的呢。
#5
有没有比较懂的人知道啊。
#6
解析顺序和执行顺序未必是一样的。从上边的实验看,解析 似乎是由左向右。
不知道oracle是否对and谓词执行顺序可以动态调整,如果是那样,就更无定论了。
不知道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
#10
Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾
按照这个说法 应该是 从右向左的
按照这个说法 应该是 从右向左的
#11
知道了。。。thank you?
#12
这条应该没有编译过去就报错了吧。
#13
这个实验详细,正解
#14
就是利用错误来检测解析顺序啊.
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
#15
执行顺序应该是从右往左
#16
从右到左…
#17
语法检查和执行两回事。
解析顺序不一定是执行顺序。
解析顺序不一定是执行顺序。
#18
oracle 根据优化器的配置,自动进行调整!
#19
你应该说的是解析的顺序
从右到左
#20
sql92 是左到右 sql99右到左
都是把数据量大的过滤条件放到最后面(右)
#21
#22
从右到左…
如果表上有索引例如索引顺序( a,b,c)
那么 尽量写成 where a =? and b= ? and c= ? and d = ?
好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.
尽量把能过滤的大条件写在后面 如标志,男女等.
如果表上有索引例如索引顺序( a,b,c)
那么 尽量写成 where a =? and b= ? and c= ? and d = ?
好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.
尽量把能过滤的大条件写在后面 如标志,男女等.
#23
从后往前执行的
#24
解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了
#25
我想10g的优化器 会帮你搞定这些位置的吧。。
cbo模式下?
cbo模式下?
#26
这个与解释器的规则有关,比如基于成本规则的,where 后面的条件是从下往上执行,也就是最后的先执行。
#27
应该看看执行计划
#28
执行肯定是右往左,
#29
从右向左
#30
可以明确的告诉你,SQl语句是从右往左执行的,如果有子查询,也会先做子查询,所以为了提高查询效率,尽量把精确条件往后写,我们做的项目表数据有的数据量达到10几亿,还有点建议,就是尽量不要用*,因为它会调用数据字典,增加查询成本。
#31
10g R2貌似没有RBO了.
感觉应该根据自己对表数据的理解,加ordered提示
感觉应该根据自己对表数据的理解,加ordered提示
#32
应该是从 是d 往 a 这边执行的,因为感觉每次出现报错都是从后往前报错的呢
#33
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。
#34
Oracle优化器会根据最优的执行计划自动调整执行顺序
#35
这个问题提的真好啊~,有没有甲骨文的人出来给证实下?
#36
正解
#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好一点
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条件写在前面还是后面,它都会首先执行.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面,它都会首先执行.
#40
你以为优化器是万能的?请你告诉我 在比较 a = 5 与 b= 6 这个过程中 哪个成本最低?
CBO在计算成本的时候大多考虑的是I/O方面的,cpu方面的就比较少
就lz的提问而言,我们假设的条件是a.b.c.d这四个条件都是一样的,都不会走索引,也就是在进行全表扫描的情况下而比较的,I/O成本已不再考虑范围内。 讨论这个最主要的作用在于使用短路原则,减少CPU进行比较的次数,其并不会减少I/O的产生,当然在大多数情况下,根据大数吃小数的原则,cpu的计算成本相比较I/O是微乎其微的.
另外我的测试虽然样本不足,但就选定的样本而言也是经过多次测试(不下于40次)的比较才得到的结果,至少可以可以看出oracle在这个样本方面所选用的算法
#41
好吧,你自己都说了,优化器都不知道a=5和b=6应该先执行哪个,那你凭什么知道呢?
在a=1 and b=2 and c=3 这种绝对平衡的where条件中(所谓绝对平衡是指数据分布,返回结果,执行方式等效率全部一样),CBO怎么执行的,有必要去考虑吗,怎么执行的结果都一样。如果where条件不平衡,同样不用考虑先后顺序,因为CBO会把所有where条件平等看待,无所谓先后。
#42
orcale 是倒序解析执行的。
#43
能淘汰最多数据的条件排在最后。
#1
是从d往a这边执行的吧。
#2
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
那怎么测试是正确的呢。
#5
有没有比较懂的人知道啊。
#6
解析顺序和执行顺序未必是一样的。从上边的实验看,解析 似乎是由左向右。
不知道oracle是否对and谓词执行顺序可以动态调整,如果是那样,就更无定论了。
不知道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
#10
Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾
按照这个说法 应该是 从右向左的
按照这个说法 应该是 从右向左的
#11
知道了。。。thank you?
#12
这条应该没有编译过去就报错了吧。
#13
这个实验详细,正解
#14
就是利用错误来检测解析顺序啊.
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
第一个和第三个都是有问题的,肯定先解析的报错.从而判断解析顺序
#15
执行顺序应该是从右往左
#16
从右到左…
#17
语法检查和执行两回事。
解析顺序不一定是执行顺序。
解析顺序不一定是执行顺序。
#18
oracle 根据优化器的配置,自动进行调整!
#19
你应该说的是解析的顺序
从右到左
#20
sql92 是左到右 sql99右到左
都是把数据量大的过滤条件放到最后面(右)
#21
#22
从右到左…
如果表上有索引例如索引顺序( a,b,c)
那么 尽量写成 where a =? and b= ? and c= ? and d = ?
好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.
尽量把能过滤的大条件写在后面 如标志,男女等.
如果表上有索引例如索引顺序( a,b,c)
那么 尽量写成 where a =? and b= ? and c= ? and d = ?
好像oracle9之后 顺序写反了 ORACLE也能利用到索引, 但是还是需要花费一定的时间,所以还是一次写好的好.
尽量把能过滤的大条件写在后面 如标志,男女等.
#23
从后往前执行的
#24
解析顺序对我们来说没什么意义,执行顺序才应该是我们应该关注的。就像你写程序一样,语法检查从左到右还是从右到左没有任何的参考价值。
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了
对于rbo来说,一般建议把过滤量大的语句写在后面,但10g后已经自动进行cbo统计了,不用过多考虑条件的放置顺序了
#25
我想10g的优化器 会帮你搞定这些位置的吧。。
cbo模式下?
cbo模式下?
#26
这个与解释器的规则有关,比如基于成本规则的,where 后面的条件是从下往上执行,也就是最后的先执行。
#27
应该看看执行计划
#28
执行肯定是右往左,
#29
从右向左
#30
可以明确的告诉你,SQl语句是从右往左执行的,如果有子查询,也会先做子查询,所以为了提高查询效率,尽量把精确条件往后写,我们做的项目表数据有的数据量达到10几亿,还有点建议,就是尽量不要用*,因为它会调用数据字典,增加查询成本。
#31
10g R2貌似没有RBO了.
感觉应该根据自己对表数据的理解,加ordered提示
感觉应该根据自己对表数据的理解,加ordered提示
#32
应该是从 是d 往 a 这边执行的,因为感觉每次出现报错都是从后往前报错的呢
#33
楼上的好多人好像是在说ORACLE 检查SQL文的语法错误是从哪里开始读。。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。
客户端发sql文到ORACLE数据库的时候
是按以下步骤来执行的
1。检查sql语法错误(包括字段之类的存在性)。
2。解析(分为两种 SOFT PARSE和HARD PARSE),如果先前已经有同样的sql文执行过了的话会采用先前的执行计划。如果是第一次执行的sql,会根据统计情报和index等结构来建立最佳的执行计划。这时候ORACLE会根据整个WHERE条件来判断最佳的执行计划。
3。根据第二步的解析结果去找相应的数据块,作最后的数据更改处理。
#34
Oracle优化器会根据最优的执行计划自动调整执行顺序
#35
这个问题提的真好啊~,有没有甲骨文的人出来给证实下?
#36
正解
#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好一点
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条件写在前面还是后面,它都会首先执行.
37L的钻研精神值得肯定,不过你这个测试第一样本量不足,第二方法也有问题,CBO的具体工作过程我不清楚,但是对于where条件,一定是优先选择执行扫描成本低,返回记录少的条件,比如where条件如果能使用到分区或者索引,那么不管你把相应的where条件写在前面还是后面,它都会首先执行.
#40
你以为优化器是万能的?请你告诉我 在比较 a = 5 与 b= 6 这个过程中 哪个成本最低?
CBO在计算成本的时候大多考虑的是I/O方面的,cpu方面的就比较少
就lz的提问而言,我们假设的条件是a.b.c.d这四个条件都是一样的,都不会走索引,也就是在进行全表扫描的情况下而比较的,I/O成本已不再考虑范围内。 讨论这个最主要的作用在于使用短路原则,减少CPU进行比较的次数,其并不会减少I/O的产生,当然在大多数情况下,根据大数吃小数的原则,cpu的计算成本相比较I/O是微乎其微的.
另外我的测试虽然样本不足,但就选定的样本而言也是经过多次测试(不下于40次)的比较才得到的结果,至少可以可以看出oracle在这个样本方面所选用的算法
#41
好吧,你自己都说了,优化器都不知道a=5和b=6应该先执行哪个,那你凭什么知道呢?
在a=1 and b=2 and c=3 这种绝对平衡的where条件中(所谓绝对平衡是指数据分布,返回结果,执行方式等效率全部一样),CBO怎么执行的,有必要去考虑吗,怎么执行的结果都一样。如果where条件不平衡,同样不用考虑先后顺序,因为CBO会把所有where条件平等看待,无所谓先后。
#42
orcale 是倒序解析执行的。
#43
能淘汰最多数据的条件排在最后。