12
返回列表 发新帖
楼主: kewin

对超长的SQL,调优该如何下手

[复制链接]
论坛徽章:
75
生肖徽章:猪
日期:2014-09-05 10:25:05指数菠菜纪念章
日期:2016-10-17 16:12:49生肖徽章:兔
日期:2015-02-05 16:49:02生肖徽章:鼠
日期:2015-02-05 16:49:02生肖徽章:鼠
日期:2015-02-05 16:49:02生肖徽章:马
日期:2015-02-05 16:49:02生肖徽章:羊
日期:2015-02-06 08:40:35生肖徽章:羊
日期:2015-02-06 08:40:34股神
日期:2015-01-05 08:27:16菲尼克斯太阳
日期:2014-12-29 13:11:51
11#
 楼主| 发表于 2011-8-19 14:45 | 只看该作者
我摘出部分SQL 做了个查询:
SQL>  SELECT jb.emplid
  2       FROM SYSADM.ps_job jb
    WHERE jb.effdt =
             (SELECT MAX (jb_ed.effdt)
                FROM SYSADM.ps_job jb_ed
               WHERE jb.emplid = jb_ed.emplid
                 AND jb.empl_rcd = jb_ed.empl_rcd
                 AND jb_ed.effdt <= SYSDATE)
      AND jb.effseq =
             (SELECT MAX (a2.effseq)
                FROM sysadm.ps_job a2
               WHERE a2.emplid = jb.emplid
                 AND a2.empl_rcd = jb.empl_rcd
                 AND a2.effdt = jb.effdt)
      AND jb.hr_status = 'A'
      AND jb.company = 'SPT'  3    4    5    6    7    8    9   10   11   12   13   14   15   16  ;

15157 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 512158586

-------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |        |     1 |    27 |  1724K  (1)| 25:44:07 |
|*  1 |  FILTER              |        |       |       |            |          |
|*  2 |   TABLE ACCESS FULL  | PS_JOB |   601K|    15M| 14429   (1)| 00:12:56 |
|   3 |   SORT AGGREGATE     |        |     1 |    18 |            |          |
|*  4 |    INDEX RANGE SCAN  | PSAJOB |    21 |   378 |     3   (0)| 00:00:01 |
|   5 |     SORT AGGREGATE   |        |     1 |    21 |            |          |
|*  6 |      INDEX RANGE SCAN| PSAJOB |     1 |    21 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("JB"."EFFDT"= (SELECT
              MAX(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))) FROM "SYSADM"."PS_J
OB"

              "JB_ED" WHERE SYS_OP_DESCEND("EFFDT") IS NOT NULL AND
              SYS_OP_DESCEND("EFFDT")>=SYS_OP_DESCEND(SYSDATE@!) AND
              "JB_ED"."EMPL_RCD"=:B1 AND "JB_ED"."EMPLID"=:B2 AND
              SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))<=SYSDATE@!) AND
              "JB"."EFFSEQ"= (SELECT MAX(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFSEQ
")))

              FROM "SYSADM"."PS_JOB" "A2" WHERE SYS_OP_DESCEND("EFFDT")=SYS_OP_D
ESCEND

              (:B3) AND "A2"."EMPL_RCD"=:B4 AND "A2"."EMPLID"=:B5 AND
              SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))=:B6))
   2 - filter("JB"."COMPANY"='SPT' AND "JB"."HR_STATUS"='A')
   4 - access("JB_ED"."EMPLID"=:B1 AND "JB_ED"."EMPL_RCD"=:B2 AND
              SYS_OP_DESCEND("EFFDT")>=SYS_OP_DESCEND(SYSDATE@!) AND
              SYS_OP_DESCEND("EFFDT") IS NOT NULL)
       filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))<=SYSDATE@!)
   6 - access("A2"."EMPLID"=:B1 AND "A2"."EMPL_RCD"=:B2 AND
              SYS_OP_DESCEND("EFFDT")=SYS_OP_DESCEND(:B3))
       filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))=:B1)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
     890077  consistent gets
      95324  physical reads
          0  redo size
     324888  bytes sent via SQL*Net to client
      11597  bytes received via SQL*Net from client
       1012  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      15157  rows processed

physical read /consistent get 都很高。

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
12#
发表于 2011-8-20 00:45 | 只看该作者
|*  2 |   TABLE ACCESS FULL  | PS_JOB |   601K|    15M| 14429   (1)| 00:12:56 |
AND jb.hr_status = 'A'
      AND jb.company = 'SPT'  

这两个列选择性如何啊,选择性好是否可以考虑建个索引
你用的是相关子查询,这个如果主表访问效率低,对整个查询影响就大了,计划走filter,类似于nested loop,对每个选择到的行访问都会触发一次子查询。

不能建立索引,考虑从业务上改写下,比如改写成join之类的

比如谓词选择性不好,像
SELECT jb.emplid
       FROM SYSADM.ps_job jb
    WHERE jb.effdt =
             (SELECT MAX (jb_ed.effdt)
                FROM SYSADM.ps_job jb_ed
               WHERE jb.emplid = jb_ed.emplid
                 AND jb.empl_rcd = jb_ed.empl_rcd
                 AND jb_ed.effdt <= SYSDATE)

考虑改写成
SELECT jb.emplid
       FROM SYSADM.ps_job jb,(SELECT jb_ed.emplid,jb_ed.empl_rcd,MAX (jb_ed.effdt) max_effdt
                FROM SYSADM.ps_job jb_ed where jb_ed.effdt <= SYSDATE
                GROUP BY jb_ed.emplid,jb_ed.empl_rcd) jb_ed_t
WHERE jb.effdt=jb_ed_t.max_effdt and jb......

使用道具 举报

回复
论坛徽章:
47
蒙奇·D·路飞
日期:2017-03-27 08:04:23马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11一汽
日期:2013-09-01 20:46:27复活蛋
日期:2013-03-13 07:55:232013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:03:322012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20
13#
发表于 2011-8-20 02:08 | 只看该作者
I haven't looked at your detailed analysis in the later messages. But to answer "对这些超长的SQL ,调优步骤是什么? 有什么好的建议?", here's my suggestion: focus on the biggest cost jump or jumps. In this case, your execution plan in message #4 has this part:


|  HASH JOIN                                                   |                     |     1 |  199 |    254 |
|   NESTED LOOPS                                               |                     |     1 |  180 |     14 |
...
|   TABLE ACCESS FULL                                          |PS_PER_ORG_ASGN      |    12K|  237K|    239 |


The total cost 283 is mostly the hash join shown above, with a cost of 254. Of this 254, 239 is contributed by the FTS of PS_PER_ORG_ASGN. So check to see if this FTS can be eliminated.

Of course this assumes your actual plan is indeed this one and cost is accurate (in the sense that it reflects the relative buffer gets among all the lines). A more accurate check of the lines in the plan is to find the line specific buffer gets:

alter session set "_rowsource_execution_statistics"=true;
--run the SQL
select * from table(dbms_xplan.display_cursor('', '', 'allstats'));

Yong Huang

[ 本帖最后由 Yong Huang 于 2011-8-19 12:38 编辑 ]

使用道具 举报

回复
论坛徽章:
5
ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51数据库板块每日发贴之星
日期:2011-07-22 01:01:02蜘蛛蛋
日期:2011-08-24 14:10:13ITPUB十周年纪念徽章
日期:2011-11-01 16:24:042012新春纪念徽章
日期:2012-01-04 11:54:26
14#
发表于 2011-8-24 22:04 | 只看该作者
呵呵 超大的SQL一样搞,没啥难度

使用道具 举报

回复
论坛徽章:
8
ITPUB十周年纪念徽章
日期:2011-11-01 16:25:22灰彻蛋
日期:2011-11-08 00:28:222012新春纪念徽章
日期:2012-01-04 11:55:052012新春纪念徽章
日期:2012-02-07 09:59:35ITPUB 11周年纪念徽章
日期:2012-10-09 18:13:332013年新春福章
日期:2013-02-25 14:51:24ITPUB社区12周年站庆徽章
日期:2013-10-08 17:44:422017金鸡报晓
日期:2017-01-10 15:33:11
15#
发表于 2011-8-26 00:48 | 只看该作者
建立几个临时表,然后用临时表再去关联,效果会好些!

使用道具 举报

回复
论坛徽章:
8
数据库板块每日发贴之星
日期:2009-06-12 01:01:02数据库板块每日发贴之星
日期:2009-06-21 01:01:01ITPUB9周年纪念徽章
日期:2010-10-08 09:32:272010广州亚运会纪念徽章:游泳
日期:2010-11-12 16:42:092011新春纪念徽章
日期:2011-02-18 11:42:502010广州亚运会纪念徽章:三项全能
日期:2011-02-26 13:07:50咸鸭蛋
日期:2011-08-30 15:51:05ITPUB十周年纪念徽章
日期:2011-11-01 16:25:22
16#
发表于 2011-8-30 19:36 | 只看该作者
初看你第一个执行计划,统计信息有问题,收集下,另外你贴出来的那小部分的sql可以考虑改写:SELECT jb.emplid
        FROM SYSADM.ps_job jb
    WHERE jb.effdt =
             (SELECT MAX (jb_ed.effdt)
                FROM SYSADM.ps_job jb_ed,SYSADM.ps_job sh
               WHERE sh.emplid = jb_ed.emplid
                 AND sh.empl_rcd = jb_ed.empl_rcd
                 AND jb_ed.effdt <= SYSDATE)
      AND jb.effseq =
             (SELECT MAX (a2.effseq)
                FROM sysadm.ps_job a2,SYSADM.ps_job sh
               WHERE a2.emplid = sh.emplid
                 AND a2.empl_rcd = sh.empl_rcd
                 AND a2.effdt = sh.effdt)
      AND jb.hr_status = 'A'
      AND jb.company = 'SPT' 
你如果查看一下执行统计,前面执行计划中的nested loop肯定有些执行了成千上万次,不慢才怪。就着一小部分,where的视图部分,内部应用的表都要到外部去join,你把这些外部的表写到视图里面,效果会好很多的。试一试啊。

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
4
授权会员
日期:2005-10-30 17:05:332010新春纪念徽章
日期:2010-03-01 11:20:00ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41
17#
发表于 2011-9-1 00:16 | 只看该作者
你搜索一下MERGE JOIN CARTESIAN,把它disable后再跑

使用道具 举报

回复

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

本版积分规则 发表回复

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