分页SQL走全表扫描导致TEMP耗尽

.查看SQL信息:
select *
  from (select   
                         a.cert_type,
               a.cert_no,
               a.cust_name,
               e.oper_no,
               to_char(c.vou_start_no + instr(c.vou_status, '0') - 1,
                       'fm00000000') as vou,
               e.bran_code
          from comr_cifbinfo   a,
               comc_box        b,
               comr_clerk_vou  c,
               auto_comc_clerk e
         where a.cert_type = '1'
           and substr(rtrim(a.cert_no), 18, 1) is not null
           and a.cert_no not in
               ('330721197211217006X', '1302011981101070315')
           and a.valid_flag = '0'
           and not exists
         (select  * from comr_cifacctno ta where ta.cust_no = a.cust_no)
           and c.vou_status like '%0%'
           and b.bran_code = e.bran_code
           and c.bran_code = e.bran_code
           and a.bank_corp_code = c.bank_corp_code
           and b.box_no = c.box_no
           and b.oper_no = e.oper_no
           and c.vou_status like '%0%'
           and c.vou_type = '11'
           and c.sub_vou_type = '0'
           and e.post_no in ('12002', '12402')
           and e.flag = '0'
         order by vou asc)
 where rownum < 2;
对应的执行计划为:
Plan hash value: 2629361789
 
-------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name            | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                 |     1 |    85 |       | 16722   (2)| 00:03:21 |
|*  1 |  COUNT STOPKEY              |                 |       |       |       |            |          |
|   2 |   VIEW                      |                 |   266 | 22610 |       | 16722   (2)| 00:03:21 |
|*  3 |    SORT ORDER BY STOPKEY    |                 |   266 | 68096 |       | 16722   (2)| 00:03:21 |
|*  4 |     HASH JOIN               |                 |   266 | 68096 |       | 16721   (2)| 00:03:21 |
|   5 |      TABLE ACCESS FULL      | COMC_BOX        |  1013 | 23299 |       |     5   (0)| 00:00:01 |
|*  6 |      HASH JOIN              |                 | 21563 |  4906K|       | 16715   (2)| 00:03:21 |
|*  7 |       TABLE ACCESS FULL     | AUTO_COMC_CLERK |   642 | 19902 |       |     9   (0)| 00:00:01 |
|*  8 |       HASH JOIN             |                 |  3594 |   708K|       | 16705   (2)| 00:03:21 |
|*  9 |        TABLE ACCESS FULL    | COMR_CLERK_VOU  |   124 | 11904 |       |  1278   (2)| 00:00:16 |
|* 10 |        HASH JOIN ANTI       |                 |   289 | 30634 |  2488K| 15427   (2)| 00:03:06 |
|* 11 |         TABLE ACCESS FULL   | COMR_CIFBINFO   | 28899 |  2144K|       |  7735   (2)| 00:01:33 |
|  12 |         INDEX FAST FULL SCAN| CIFACCTNO_IDX2  |  2110K|    60M|       |  3326   (2)| 00:00:40 |
-------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<2)
   3 - filter(ROWNUM<2)
   4 - access("B"."BRAN_CODE"="E"."BRAN_CODE" AND "B"."BOX_NO"="C"."BOX_NO" AND 
              "B"."OPER_NO"="E"."OPER_NO")
   6 - access("C"."BRAN_CODE"="E"."BRAN_CODE")
   7 - filter(("E"."POST_NO"='12002' OR "E"."POST_NO"='12402') AND "E"."FLAG"='0')
   8 - access("A"."BANK_CORP_CODE"="C"."BANK_CORP_CODE")
   9 - filter("C"."VOU_TYPE"=11 AND "C"."VOU_STATUS" LIKE '%0%' AND "C"."VOU_STATUS" IS NOT 
              NULL AND "C"."SUB_VOU_TYPE"=0)
  10 - access("TA"."CUST_NO"="A"."CUST_NO")
  11 - filter(SUBSTR(RTRIM("A"."CERT_NO"),18,1) IS NOT NULL AND "A"."CERT_TYPE"='1' AND 
              "A"."VALID_FLAG"='0' AND "A"."CERT_NO"<>'330721197211217006X' AND 
              "A"."CERT_NO"<>'1302011981101070315')

此SQL是典型的分页SQL,按照COMR_CLERK_VOU的to_char(c.vou_start_no + instr(c.vou_status, '0') - 1, 'fm00000000') as vou进行排序,这个走全表扫描,则会对整个表进行排序在取一条,实际上取一条不需要对整个表排序,分页语句不能出现SORT ORDER BY STOPKEY。
3.创建索引和添加hints:
create index idx_comr_clerk_vou on comr_clerk_vou(vou_type,sub_vou_type,to_char(vou_start_no + instr(vou_status, '0') - 1,
                    'fm00000000'))

select *
  from (select   
                       /*+ index_asc(c  idx_comr_clerk_vou)   */  a.cert_type,
               a.cert_no,
               a.cust_name,
               e.oper_no,
               to_char(c.vou_start_no + instr(c.vou_status, '0') - 1,
                       'fm00000000') as vou,
               e.bran_code
          from comr_cifbinfo   a,
               comc_box        b,
               comr_clerk_vou  c,
               auto_comc_clerk e
         where a.cert_type = '1'
           and substr(rtrim(a.cert_no), 18, 1) is not null
           and a.cert_no not in
               ('330721197211217006X', '1302011981101070315')
           and a.valid_flag = '0'
           and not exists
         (select  * from comr_cifacctno ta where ta.cust_no = a.cust_no)
           and c.vou_status like '%0%'
           and b.bran_code = e.bran_code
           and c.bran_code = e.bran_code
           and a.bank_corp_code = c.bank_corp_code
           and b.box_no = c.box_no
           and b.oper_no = e.oper_no
           and c.vou_status like '%0%'
           and c.vou_type = '11'
           and c.sub_vou_type = '0'
           and e.post_no in ('12002', '12402')
           and e.flag = '0'
         order by vou asc)
 where rownum < 2;
此时查看执行计划:
Plan hash value: 2236318696
 
---------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                     |     1 |    85 |   790   (1)| 00:00:10 |
|*  1 |  COUNT STOPKEY                    |                     |       |       |            |          |
|   2 |   VIEW                            |                     |     1 |    85 |   790   (1)| 00:00:10 |
|   3 |    NESTED LOOPS ANTI              |                     |     1 |   256 |   790   (1)| 00:00:10 |
|   4 |     NESTED LOOPS                  |                     |   100 | 22600 |   589   (1)| 00:00:08 |
|   5 |      NESTED LOOPS                 |                     |     1 |   150 |   361   (1)| 00:00:05 |
|   6 |       NESTED LOOPS                |                     |   168 | 19992 |   284   (1)| 00:00:04 |
|*  7 |        TABLE ACCESS BY INDEX ROWID| COMR_CLERK_VOU      |   124 | 11904 |   232   (0)| 00:00:03 |
|*  8 |         INDEX RANGE SCAN          | IDX_COMR_CLERK_VOU  |   280 |       |     3   (0)| 00:00:01 |
|*  9 |        TABLE ACCESS FULL          | COMC_BOX            |    12 |   276 |     4   (0)| 00:00:01 |
|* 10 |       TABLE ACCESS BY INDEX ROWID | AUTO_COMC_CLERK     |     1 |    31 |     1   (0)| 00:00:01 |
|* 11 |        INDEX UNIQUE SCAN          | AUTO_COMC_CLERK_INX |     1 |       |     0   (0)| 00:00:01 |
|* 12 |      TABLE ACCESS BY INDEX ROWID  | COMR_CIFBINFO       |   100 |  7600 |   229   (1)| 00:00:03 |
|* 13 |       INDEX RANGE SCAN            | CIFB_IDX2           |   101 |       |   128   (2)| 00:00:02 |
|* 14 |     INDEX RANGE SCAN              | CIFACCTNO_IDX2      |  2110K|    60M|     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM<2)
   7 - filter("C"."VOU_STATUS" LIKE '%0%' AND "C"."VOU_STATUS" IS NOT NULL)
   8 - access("C"."VOU_TYPE"=11 AND "C"."SUB_VOU_TYPE"=0)
   9 - filter("B"."BOX_NO"="C"."BOX_NO")
  10 - filter(("E"."POST_NO"='12002' OR "E"."POST_NO"='12402') AND "E"."FLAG"='0' AND 
              "B"."BRAN_CODE"="E"."BRAN_CODE" AND "C"."BRAN_CODE"="E"."BRAN_CODE")
  11 - access("B"."OPER_NO"="E"."OPER_NO")
  12 - filter("A"."VALID_FLAG"='0')
  13 - access("A"."CERT_TYPE"='1' AND "A"."BANK_CORP_CODE"="C"."BANK_CORP_CODE")
       filter(SUBSTR(RTRIM("A"."CERT_NO"),18,1) IS NOT NULL AND 
              "A"."CERT_NO"<>'330721197211217006X' AND "A"."CERT_NO"<>'1302011981101070315' AND 
              "A"."BANK_CORP_CODE"="C"."BANK_CORP_CODE")
  14 - access("TA"."CUST_NO"="A"."CUST_NO")

此时SORT ORDER BY STOPKEY消失,通过索引访问最理想的情况只需要访问一条数据就停止索引扫描,这样节省了大量的排序工作。

原文地址:https://www.cnblogs.com/hzcya1995/p/13352151.html