查看: 9389|回复: 15

写法一样的SQL,执行计划一样,为什么消耗时间差一半?

[复制链接]
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
跳转到指定楼层
1#
发表于 2005-2-28 16:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
两条SQL的执行计划一样,为什么消耗的时间不一样?请看下面两条SQL,功能是一样的,只是写法不一样。第一条时间为Elapsed: 00:00:02.32,第二条为Elapsed: 00:00:04.55, 多次测试证明,第二条时间确实比第一条慢。
SQL> select a.projectid,b.itemname,
       sum(decode(a.spiece,null,0,a.spiece)) as spiece,
       sum(decode(a.sgweigth,null,0,a.sgweigth)) as weight,
       0,0,
       count(*) as ballot
  from t_bill_base a,t_iteminfo b where
   a.projectid= b.itemcode
and to_char(a.collectiontime, 'yyyy-MM-dd') ='2005-02-28'
group by a.projectid, b.itemname;  
PROJECTID  ITEMNAME       SPIECE     WEIGHT          0          0     BALLOT
---------- ---------- ---------- ---------- ---------- ---------- ----------
CHQC       ????               61      646.3          0          0          5
CQYY       ????               26        264          0          0          2
XNLD       ????                6      76.06          0          0          3
ZBYY       ????                1        3.7          0          0          1
ALKYY      ?????               8      38.88          0          0          4

Elapsed: 00:00:02.32

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_BILL_BASE'
   3    2       NESTED LOOPS
   4    3         TABLE ACCESS (FULL) OF 'T_ITEMINFO'
   5    3         INDEX (RANGE SCAN) OF 'I_T_ BILL_BASE_POD' (NON
          -UNIQUE)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1771  consistent gets
          0  physical reads
          0  redo size
       1048  bytes sent via SQL*Net to client
        655  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed

SQL>
select a.projectid,b.itemname,
       sum(case when a.spiece is null then 0 else a.spiece end) as spiece,
       sum(case when a.sgweigth is null then 0 else a.sgweigth end) as weight,0,0,
       count(*) as ballot
  from t_bill_base a inner join t_iteminfo b on a.projectid = b.itemcode
where 1 = 1 and to_char(a.collectiontime, 'yyyy-MM-dd HH24:mm:ss') >=
       '2005-02-28 00:00:00' and
       to_char(a.collectiontime, 'yyyy-MM-dd HH24:mm:ss') <=
       '2005-02-28 23:59:59'
group by a.projectid, b.itemname;
PROJECTID  ITEMNAME       SPIECE     WEIGHT        VOL        FEE     BALLOT
---------- ---------- ---------- ---------- ---------- ---------- ----------
CHQC       ????               61      646.3          0          0          5
CQYY       ????               26        264          0          0          2
XNLD       ????                6      76.06          0          0          3
ZBYY       ????                1        3.7          0          0          1
ALKYY      ?????               8      38.88          0          0          4

Elapsed: 00:00:04.55

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_BILL_BASE'
   3    2       NESTED LOOPS
   4    3         TABLE ACCESS (FULL) OF 'T_ITEMINFO'
   5    3         INDEX (RANGE SCAN) OF 'I_T_BILL_BASE_POD' (NON
          -UNIQUE)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1771  consistent gets
          0  physical reads
          0  redo size
       1052  bytes sent via SQL*Net to client
        655  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
2#
 楼主| 发表于 2005-2-28 16:25 | 只看该作者
标题应是"写法不一样的SQL,执行计划一样,为什么消耗时间差一半?"

另外,t_bill_base 有200W条记录,t_iteminfo 有100条记录

使用道具 举报

回复
论坛徽章:
5
授权会员
日期:2005-10-30 17:05:33生肖徽章2007版:鸡
日期:2008-01-02 17:35:53生肖徽章2007版:鼠
日期:2008-01-02 17:35:532015年新春福章
日期:2015-03-04 14:19:112015年新春福章
日期:2015-03-06 11:57:31
3#
发表于 2005-2-28 17:25 | 只看该作者
这个“一半”只有2秒钟!
从逻辑读上看是一样的,这样看来应该是to_char的执行次数和比较条件多一个造成这种差异。
问一下:t_bill_base中满足时间条件的记录有多少条?

使用道具 举报

回复
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
4#
 楼主| 发表于 2005-2-28 17:41 | 只看该作者
这个是简单统计,条件相等的只有300条,我试了把上面的SQL把时间改成1个月,也是第一条快第二条的2倍左右

使用道具 举报

回复
论坛徽章:
5
授权会员
日期:2005-10-30 17:05:33生肖徽章2007版:鸡
日期:2008-01-02 17:35:53生肖徽章2007版:鼠
日期:2008-01-02 17:35:532015年新春福章
日期:2015-03-04 14:19:112015年新春福章
日期:2015-03-06 11:57:31
5#
发表于 2005-2-28 20:20 | 只看该作者
你的意思是t_bill_base和t_iteminfo建立连接后记录数是多少?是不是最后筛选是根据t_bill_base的时间条件进行的?
你试一下把SQL1的条件
to_char(a.collectiontime, 'yyyy-MM-dd') ='2005-02-28'
改为:
a.collectiontime between to_date('2005-02-08 00:00:00','yyyy-mm-dd hh24:mi:ss') and to_date('2005-02-08 23:59:59','yyyy-mm-dd hh24:mi:ss')
试一下,会不会快一些?
建议你做个SQL Trace,用tkprof看一下2个SQL的CPU消耗是否相当?

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
6#
发表于 2005-3-1 00:39 | 只看该作者

Re: 写法一样的SQL,执行计划一样,为什么消耗时间差一半?

最初由 weijsh 发布
[B]两条SQL的执行计划一样,为什么消耗的时间不一样?请看下面两条SQL,功能是一样的,只是写法不一样。第一条时间为Elapsed: 00:00:02.32,第二条为Elapsed: 00:00:04.55, 多次测试证明,第二条时间确实比第一条慢。
SQL> select a.projectid,b.itemname,
       sum(decode(a.spiece,null,0,a.spiece)) as spiece,
       sum(decode(a.sgweigth,null,0,a.sgweigth)) as weight,
       0,0,
       count(*) as ballot
  from t_bill_base a,t_iteminfo b where
   a.projectid= b.itemcode
and to_char(a.collectiontime, 'yyyy-MM-dd') ='2005-02-28'
group by a.projectid, b.itemname;  
PROJECTID  ITEMNAME       SPIECE     WEIGHT          0          0     BALLOT
---------- ---------- ---------- ---------- ---------- ---------- ----------
CHQC       ????               61      646.3          0          0          5
CQYY       ????               26        264          0          0          2
XNLD       ????                6      76.06          0          0          3
ZBYY       ????                1        3.7          0          0          1
ALKYY      ?????               8      38.88          0          0          4

Elapsed: 00:00:02.32

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_BILL_BASE'
   3    2       NESTED LOOPS
   4    3         TABLE ACCESS (FULL) OF 'T_ITEMINFO'
   5    3         INDEX (RANGE SCAN) OF 'I_T_ BILL_BASE_POD' (NON
          -UNIQUE)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1771  consistent gets
          0  physical reads
          0  redo size
       1048  bytes sent via SQL*Net to client
        655  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed

SQL>
select a.projectid,b.itemname,
       sum(case when a.spiece is null then 0 else a.spiece end) as spiece,
       sum(case when a.sgweigth is null then 0 else a.sgweigth end) as weight,0,0,
       count(*) as ballot
  from t_bill_base a inner join t_iteminfo b on a.projectid = b.itemcode
where 1 = 1 and to_char(a.collectiontime, 'yyyy-MM-dd HH24:mm:ss') >=
       '2005-02-28 00:00:00' and
       to_char(a.collectiontime, 'yyyy-MM-dd HH24:mm:ss') <=
       '2005-02-28 23:59:59'
group by a.projectid, b.itemname;
PROJECTID  ITEMNAME       SPIECE     WEIGHT        VOL        FEE     BALLOT
---------- ---------- ---------- ---------- ---------- ---------- ----------
CHQC       ????               61      646.3          0          0          5
CQYY       ????               26        264          0          0          2
XNLD       ????                6      76.06          0          0          3
ZBYY       ????                1        3.7          0          0          1
ALKYY      ?????               8      38.88          0          0          4

Elapsed: 00:00:04.55

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'T_BILL_BASE'
   3    2       NESTED LOOPS
   4    3         TABLE ACCESS (FULL) OF 'T_ITEMINFO'
   5    3         INDEX (RANGE SCAN) OF 'I_T_BILL_BASE_POD' (NON
          -UNIQUE)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1771  consistent gets
          0  physical reads
          0  redo size
       1052  bytes sent via SQL*Net to client
        655  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed [/B]


简单的说,由于你sql的写法,导致第二条sql执行的数据类型转化操作比第一条sql多了一倍,因此,第二条sql所需的时间也基本上是第一条sql的二倍。
如果你把查询语句and a.collectiontime >= to_date('2005-02-28', 'yyyy-MM-dd') and a.collectiontime < to_date('2005-02-29', 'yyyy-MM-dd')
在不改变执行计划的前提下就可以提高效率。

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
7#
发表于 2005-3-1 00:41 | 只看该作者
具体描述可以参考这里:http://blog.itpub.net/post/468/20038

使用道具 举报

回复
论坛徽章:
5
行业板块每日发贴之星
日期:2005-08-03 01:02:33行业板块每日发贴之星
日期:2005-12-02 01:02:58会员2006贡献徽章
日期:2006-04-17 13:46:342009日食纪念
日期:2009-07-22 09:30:00祖国60周年纪念徽章
日期:2009-10-09 08:28:00
8#
发表于 2005-3-1 10:49 | 只看该作者
在列名前加函数, 在开发过程中是基本不允许出现的.
要这个规矩告诉开发人员.

使用道具 举报

回复
论坛徽章:
168
马上加薪
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-01-04 11:49:54蜘蛛蛋
日期:2011-12-05 16:08:56ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41设计板块每日发贴之星
日期:2011-07-22 01:01:02ITPUB官方微博粉丝徽章
日期:2011-06-30 12:30:16管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:33
9#
发表于 2005-3-1 11:08 | 只看该作者
最初由 david2000 发布
[B]在列名前加函数, 在开发过程中是基本不允许出现的.
要这个规矩告诉开发人员. [/B]


为何不行?比如处理空值之类的加nvl也未尝不可.
提升性能的话,建立函数索引即可.

使用道具 举报

回复
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
10#
 楼主| 发表于 2005-3-1 11:24 | 只看该作者
在开发中不用列函数几呼不可能的,在where 子句后面使用函数可用函数索引,否则引用了函数执行计划是不走索引的

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表