ORACLE SQL性能比较

时间:2021-09-17 18:32:45
两个SQL烦请大家指点下 KUNY是一个很大的表, KUN相对较小
请问这两个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


引用 1 楼 wmxcn2000 的回复:
没有区别的,不过还是建议你跑跑看;

在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?

#3


引用 2 楼 xuxiaoyinliu 的回复:
Quote: 引用 1 楼 wmxcn2000 的回复:

没有区别的,不过还是建议你跑跑看;

在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?

oracle   CBO会做查询转换

#4


执行计划贴出来看下

#5


如果KUNY表超级大,那么第一种方法应该要占优一些。表小了,就没有区别了。
你可以对比一下两种方法的时间。

#6


如果表小,第二种可能还占优一些,因为少了一级查询。

#7


具体看下执行计划了,应该是没有区别的

不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。

#8


二者执行计划完全一样

#9


ORACLE SQL性能比较

#10


引用 9 楼 xuxiaoyinliu 的回复:
ORACLE SQL性能比较


数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、

#11


引用 10 楼 killvoon 的回复:
Quote: 引用 9 楼 xuxiaoyinliu 的回复:

ORACLE SQL性能比较


数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、

我把所有的WHERE条件都去掉麻烦你再看下

#12


SQL1
ORACLE SQL性能比较
SQL2
ORACLE SQL性能比较

#13


更新下SQL2的执行计划
ORACLE SQL性能比较

#14


引用 13 楼 xuxiaoyinliu 的回复:
更新下SQL2的执行计划
ORACLE SQL性能比较


咳咳,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语句是一样的。。。。。。

#1


没有区别的,不过还是建议你跑跑看;

#2


引用 1 楼 wmxcn2000 的回复:
没有区别的,不过还是建议你跑跑看;

在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?

#3


引用 2 楼 xuxiaoyinliu 的回复:
Quote: 引用 1 楼 wmxcn2000 的回复:

没有区别的,不过还是建议你跑跑看;

在第一个SQL里我本意是想在KUNY这个表里取出符合条件的数据缩小取值范围然后再与KUN表关联,以为这样会比下面的写法好一些但是看了下执行计划,好像没有什么区别,请问为什么会这样?

oracle   CBO会做查询转换

#4


执行计划贴出来看下

#5


如果KUNY表超级大,那么第一种方法应该要占优一些。表小了,就没有区别了。
你可以对比一下两种方法的时间。

#6


如果表小,第二种可能还占优一些,因为少了一级查询。

#7


具体看下执行计划了,应该是没有区别的

不知道表的具体数据量,如果KUNY和 KUN 都挺大的话,oracle应该判断出来走hash join。kuny表应该是有对应索引可以走,kun表应该是全表扫描。

#8


二者执行计划完全一样

#9


ORACLE SQL性能比较

#10


引用 9 楼 xuxiaoyinliu 的回复:
ORACLE SQL性能比较


数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、

#11


引用 10 楼 killvoon 的回复:
Quote: 引用 9 楼 xuxiaoyinliu 的回复:

ORACLE SQL性能比较


数据量不大啊,基数那么小。是不是统计信息不对呀,不符合你上面说的“KUNY是一个很大的表, KUN相对较小”。 kun表很小么、

我把所有的WHERE条件都去掉麻烦你再看下

#12


SQL1
ORACLE SQL性能比较
SQL2
ORACLE SQL性能比较

#13


更新下SQL2的执行计划
ORACLE SQL性能比较

#14


引用 13 楼 xuxiaoyinliu 的回复:
更新下SQL2的执行计划
ORACLE SQL性能比较


咳咳,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语句是一样的。。。。。。