请问这两个SQL在执行效率上有区别吗?
SQL1:
SELECT M.*,
R.RECHARGE_ACCOUNT AS "account",
FROM (SELECT O.ORDER_ID,
O.ORDER_FAVEVALUE AS "face",
FROM KUNY O
WHERE O.STARTTIME >=
TO_DATE('2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND O.STARTTIME <
TO_DATE('2016-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND O.USERID = 11045) M,
KUN R
WHERE M.ORDER_ID = R.ORDER_ID
AND R.PRODUCT_TYPE NOT IN (48, 49, 50)
SQL2:
SELECT
O.ORDER_FAVEVALUE AS "face",
R.RECHARGE_ACCOUNT AS "account",
FROM KUNY O, KUN R
WHERE O.ORDER_ID = R.ORDER_ID
AND O.STARTTIME >=
TO_DATE('2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND O.STARTTIME <
TO_DATE('2016-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND O.USERID = 11045
AND R.PRODUCT_TYPE NOT IN (48, 49, 50)
15 个解决方案
#1
没有区别的,不过还是建议你跑跑看;
#2
在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?
#3
oracle CBO会做查询转换
#4
执行计划贴出来看下
#5
如果KUNY表超级大,那么第一种方法应该要占优一些。表小了,就没有区别了。
你可以对比一下两种方法的时间。
你可以对比一下两种方法的时间。
#6
如果表小,第二种可能还占优一些,因为少了一级查询。
#7
具体看下执行计划了,应该是没有区别的
不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。
不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。
#8
二者执行计划完全一样
#9
#10
数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、
#11
数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、
我把所有的WHERE条件都去掉麻烦你再看下
#12
SQL1
SQL2
SQL2
#13
更新下SQL2的执行计划
#14
更新下SQL2的执行计划
咳咳,SQL2的语句,你是不是把表关联条件也给去掉了。。。生成了一个笛卡尔的执行计划。
原来的执行计划生成nestloop应该是你where 谓词条件过滤性好,得到的结果集很小,oracle认为选择nestloop的方式效率高。
至于你所疑惑的为什么SQL1和SQL2,写法不同,执行计划相同的问题,对于oracle而言,多表查询,oracle都是要做两表两两关联的。你SQL1采用内嵌视图的写法,优化器也是要展开,将该内嵌视图中的表和其他表做关联查询。
就像你在sql语句中使用了一些view,优化器也会根据规则,符合条件的情况下做视图合并()
还有常见的子查询写法,如in,exists,not in,not exists,优化器也是优先做子查询扩展,将子查询中的表和主语句from后面的表做关联的,扩展不了的话,才会做filter的执行计划。
所以,不管你写法多么复杂,不同,oracle优化器都是尽量实现表与表之间的直接关联,为此,oracle会做一些查询转换,诸如视图合并,子查询扩展,谓词推进等。。。。。
#15
换句话说,oracle在处理一条sql语句的时候,会将你的sql语句根据cbo优化器的一些规则进行改写。。
而你的SQL1的写法,会被改成SQL2的写法。。。所以,对于oracle而言,这两条sql语句是一样的。。。。。。
而你的SQL1的写法,会被改成SQL2的写法。。。所以,对于oracle而言,这两条sql语句是一样的。。。。。。
#1
没有区别的,不过还是建议你跑跑看;
#2
没有区别的,不过还是建议你跑跑看;
在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?
#3
没有区别的,不过还是建议你跑跑看;
在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?
oracle CBO会做查询转换
#4
执行计划贴出来看下
#5
如果KUNY表超级大,那么第一种方法应该要占优一些。表小了,就没有区别了。
你可以对比一下两种方法的时间。
你可以对比一下两种方法的时间。
#6
如果表小,第二种可能还占优一些,因为少了一级查询。
#7
具体看下执行计划了,应该是没有区别的
不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。
不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。
#8
二者执行计划完全一样
#9
#10
数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、
#11
数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、
我把所有的WHERE条件都去掉麻烦你再看下
#12
SQL1
SQL2
SQL2
#13
更新下SQL2的执行计划
#14
更新下SQL2的执行计划
咳咳,SQL2的语句,你是不是把表关联条件也给去掉了。。。生成了一个笛卡尔的执行计划。
原来的执行计划生成nestloop应该是你where 谓词条件过滤性好,得到的结果集很小,oracle认为选择nestloop的方式效率高。
至于你所疑惑的为什么SQL1和SQL2,写法不同,执行计划相同的问题,对于oracle而言,多表查询,oracle都是要做两表两两关联的。你SQL1采用内嵌视图的写法,优化器也是要展开,将该内嵌视图中的表和其他表做关联查询。
就像你在sql语句中使用了一些view,优化器也会根据规则,符合条件的情况下做视图合并()
还有常见的子查询写法,如in,exists,not in,not exists,优化器也是优先做子查询扩展,将子查询中的表和主语句from后面的表做关联的,扩展不了的话,才会做filter的执行计划。
所以,不管你写法多么复杂,不同,oracle优化器都是尽量实现表与表之间的直接关联,为此,oracle会做一些查询转换,诸如视图合并,子查询扩展,谓词推进等。。。。。
#15
换句话说,oracle在处理一条sql语句的时候,会将你的sql语句根据cbo优化器的一些规则进行改写。。
而你的SQL1的写法,会被改成SQL2的写法。。。所以,对于oracle而言,这两条sql语句是一样的。。。。。。
而你的SQL1的写法,会被改成SQL2的写法。。。所以,对于oracle而言,这两条sql语句是一样的。。。。。。