Optimize SQL with Gael-a typical case of subquery Optimization

Source: Internet
Author: User
Tags sorts

When it was about to get off work last Friday, Galle sent an SQL

select tpc.policy_id,       tcm.policy_code,       tpf.organ_id,       to_char(tpf.insert_time, 'YYYY-MM-DD') As insert_time,       tpc.change_id,       d.policy_code,       e.company_name,       f.real_name,       tpf.fee_type,       sum(tpf.pay_balance) as pay_balance,       c.actual_type,       tpc.notice_code,       d.policy_type,       g.mode_name as pay_mode  from t_policy_change    tpc,       t_contract_master  tcm,       t_policy_fee       tpf,       t_fee_type         c,       t_contract_master  d,       t_company_customer e,       t_customer         f,       t_pay_mode         g where tpc.change_id = tpf.change_id   and tpf.policy_id = d.policy_id   and tcm.policy_id = tpc.policy_id   and tpf.receiv_status = 1    and tpf.fee_status = 1   and tpf.payment_id is null   and tpf.fee_type = c.type_id   and tpf.pay_mode = g.mode_id   and d.company_id = e.company_id(+)   and d.applicant_id = f.customer_id(+)   and tpf.organ_id in       (select          organ_id          from t_company_organ         start with organ_id = '101'        connect by prior organ_id = parent_id) group by tpc.policy_id,          tpc.change_id,          tpf.fee_type,          to_char(tpf.insert_time, 'YYYY-MM-DD'),          c.actual_type,          d.policy_code,          g.mode_name,          e.company_name,          f.real_name,          tpc.notice_code,          d.policy_type,          tpf.organ_id,          tcm.policy_code order by change_id, fee_typeSQL> select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Id  | Operation                           |  Name                       | Rows  | Bytes |TempSpc| Cost (%CPU)|----------------------------------------------------------------------------------------------------------------|   0 | SELECT STATEMENT                    |                             | 45962 |    11M|       | 45650   (0)||   1 |  SORT GROUP BY                      |                             | 45962 |    11M|    23M| 45650   (0)||*  2 |   HASH JOIN                         |                             | 45962 |    11M|       | 43908   (0)||   3 |    INDEX FULL SCAN                  | T_FEE_TYPE_IDX_003          |   106 |   636 |       |     1   (0)||   4 |    NESTED LOOPS OUTER               |                             | 45962 |    11M|       | 43906   (0)||*  5 |     HASH JOIN                       |                             | 45962 |  7271K|  6824K| 43905   (0)||   6 |      NESTED LOOPS                   |                             | 45961 |  6283K|       | 42312   (0)||*  7 |       HASH JOIN SEMI                |                             | 45961 |  5655K|    50M| 33120   (1)||*  8 |        HASH JOIN OUTER              |                             |   400K|    45M|    44M| 32315   (1)||*  9 |         HASH JOIN                   |                             |   400K|    39M|    27M| 26943   (0)||* 10 |          HASH JOIN                  |                             |   400K|    23M|       | 16111   (0)||  11 |           TABLE ACCESS FULL         | T_PAY_MODE                  |    25 |   525 |       |     2   (0)||* 12 |           TABLE ACCESS FULL         | T_POLICY_FEE                |   400K|    15M|       | 16107   (0)||  13 |          TABLE ACCESS FULL          | T_CONTRACT_MASTER           |  1136K|    46M|       |  9437   (0)||  14 |         VIEW                        | index_join_007            |  2028K|    30M|       |            ||* 15 |          HASH JOIN                  |                             |   400K|    45M|    44M| 32315   (1)||  16 |           INDEX FAST FULL SCAN      | PK_T_CUSTOMER               |  2028K|    30M|       |   548   (0)||  17 |           INDEX FAST FULL SCAN      | IDX_CUSTOMER__BIR_REAL_GEN  |  2028K|    30M|       |   548   (0)||  18 |        VIEW                         | VW_NSO_1                    |     7 |    42 |       |            ||* 19 |         CONNECT BY WITH FILTERING   |                             |       |       |       |            ||  20 |          NESTED LOOPS               |                             |       |       |       |            ||* 21 |           INDEX UNIQUE SCAN         | PK_T_COMPANY_ORGAN          |     1 |     6 |       |            ||  22 |           TABLE ACCESS BY USER ROWID| T_COMPANY_ORGAN             |       |       |       |            ||  23 |          NESTED LOOPS               |                             |       |       |       |            ||  24 |           BUFFER SORT               |                             |     7 |    70 |       |            ||  25 |            CONNECT BY PUMP          |                             |       |       |       |            ||* 26 |           INDEX RANGE SCAN          | T_COMPANY_ORGAN_IDX_002     |     7 |    70 |       |     1   (0)||  27 |       TABLE ACCESS BY INDEX ROWID   | T_POLICY_CHANGE             |     1 |    14 |       |     2  (50)||* 28 |        INDEX UNIQUE SCAN            | PK_T_POLICY_CHANGE          |     1 |       |       |     1   (0)||  29 |      INDEX FAST FULL SCAN           | IDX1_ACCEPT_DATE            |  1136K|    23M|       |   899   (0)||  30 |     TABLE ACCESS BY INDEX ROWID     | T_COMPANY_CUSTOMER          |     1 |    90 |       |     2  (50)||* 31 |      INDEX UNIQUE SCAN              | PK_T_COMPANY_CUSTOMER       |     1 |       |       |            |----------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   2 - access("TPF"."FEE_TYPE"="C"."TYPE_ID")   5 - access("TCM"."POLICY_ID"="TPC"."POLICY_ID")   7 - access("TPF"."ORGAN_ID"="VW_NSO_1"."$nso_col_1")   8 - access("D"."APPLICANT_ID"="F"."CUSTOMER_ID"(+))   9 - access("TPF"."POLICY_ID"="D"."POLICY_ID")  10 - access("TPF"."PAY_MODE"="G"."MODE_ID")  12 - filter("TPF"."CHANGE_ID" IS NOT NULL AND TO_NUMBER("TPF"."RECEIV_STATUS")=1 AND "TPF"."FEE_STATUS"=1 AND              "TPF"."PAYMENT_ID" IS NULL)  15 - access("indexjoin_alias_012".ROWID="indexjoin_alias_011".ROWID)  19 - filter("T_COMPANY_ORGAN"."ORGAN_ID"='101')  21 - access("T_COMPANY_ORGAN"."ORGAN_ID"='101')  26 - access("T_COMPANY_ORGAN"."PARENT_ID"=NULL)  28 - access("TPC"."CHANGE_ID"="TPF"."CHANGE_ID")  31 - access("D"."COMPANY_ID"="E"."COMPANY_ID"(+))55 rows selectedStatistics----------------------------------------------------------         21  recursive calls          0  db block gets     125082  consistent gets      21149  physical reads          0  redo size       2448  bytes sent via SQL*Net to client        656  bytes received via SQL*Net from client          2  SQL*Net roundtrips to/from client          4  sorts (memory)          0  sorts (disk)         11  rows processed

 

It takes 21 seconds for this SQL statement to run. It takes about yuan to read the SQL statement in logic and asks if I can optimize the SQL statement. It took me about one minute to optimize this SQL statement, because it was too simple.
You can see that this SQL statement is a typical join statement. To deal with such SQL statements, the table must be indexed. But from the execution plan, there is a 10 million rows table t_contract_master which uses a full table scan,
The rows of t_policy_1_table are also scanned in the full table, so it is not slow. Then, the SQL filter condition has an in subquery.
(Select
Organ_id
From t_company_organ
Start with organ_id = '123'
Connect by prior organ_id = parent_id)
In terms of the Execution Plan, CBO performs unnest on the son's query, because CBO generally thinks that the performance of the subquery is better than that of the filter after the subquery is unnest.

So I asked Gael to query the number of rows returned by the subquery.
Select organ_id
From t_company_organ
Start with organ_id = '123'
Connect by prior organ_id = parent_id --- Gael says it returns 1 line

For a subquery, if it returns very little data (one row is returned here), it can be used as a filter, and the filter is basically executed in the final de-phase of the SQL statement, in this way, t_policy_fee can be indexed.
So I added an hint to this subquery to disable the extension of the subquery.

Select TPC. policy_id, TCM. policy_code, TPF. organ_id, to_char (TPF. insert_time, 'yyyy-MM-DD ') as insert_time, TPC. change_id, D. policy_code, E. company_name, F. real_name, TPF. fee_type, sum (TPF. pay_balance) as pay_balance, C. actual_type, TPC. notice_code, D. policy_type, G. mode_name as pay_mode from t_policy_change TPC, t_contract_master TCM, t_policy_effectpf, t_fee_type C, t_contract_master D, t_company_customer E, t_customer F, t_pay_mode g where TPC. change_id = TPF. change_id and TPF. policy_id = D. policy_id and TCM. policy_id = TPC. policy_id and TPF. pai_status = '1' --- there were no quotation marks here. I forgot to write ''to the development sb. I asked gel to add it. If it was not added, indexes and TPF could not be used. fee_status = 1 and TPF. payment_id is null and TPF. fee_type = C. type_id and TPF. pay_mode = G. mode_id and D. company_id = E. company_id (+) and D. applicant_id = f. customer_id (+) and TPF. organ_id in (select/* + no_unnest */-- The organ_id added after the hint here from t_company_organ start with organ_id = '2013' connect by prior organ_id = parent_id) group by TPC. policy_id, TPC. change_id, TPF. fee_type, to_char (TPF. insert_time, 'yyyy-MM-DD '), C. actual_type, D. policy_code, G. mode_name, E. company_name, F. real_name, TPC. notice_code, D. policy_type, TPF. organ_id, TCM. policy_code order by change_id, fee_typesql> select * from table (dbms_xplan.display); plan_table_output tables | ID | operation | Name | rows | bytes | tempspc | cost (% CPU) | statement | 0 | SELECT statement | 20026 | Statement 8 k | 68615 (30) | 1 | sort group by | 20026 | Statement 8 k | 10 M | 28563 (0) | * 2 | filter | 3 | nested loops | 20026 | Bytes 8 k | 27812 (0) | 4 | nested loops | 20026 | 4498k | 23807 (0) | 5 | nested loops outer | 20026 | 4224k | 19802 (0) | 6 | nested loops outer | 20026 | 3911k | 15797 (0) | 7 | nested loops | 20026 | 2151k | 15796 (0) | * 8 | hash join | 20026 | 1310k | 11791 (0) | 9 | index full scan | t_fee_type_idx_003 | 106 | 636 | 1 (0) | * 10 | hash join | 20026 | 1192k | 11789 (0) | 11 | table access full | t_pay_mode | 25 | 525 | 2 (0) | * 12 | table access by index rowid | t_policy_fee | 20026 | 782k | 11786 (0) | * 13 | index range scan | idx_policy_fee1_1__status | 1243k | 10188 (0) | 14 | table access by index rowid | t_contract_master | 1 | 43 | 2 (50) | * 15 | index unique scan | pk_t_contract_master | 1 | 1 (0) | 16 | table access by index rowid | t_company_customer | 1 | 90 | 2 (50) | * 17 | index unique scan | pk_t_company_customer | 1 | 18 | table access by index rowid | t_customer | 1 | 16 | 2 (50) | * 19 | index unique scan | pk_t_customer | 1 | 1 (0) | 20 | table access by index rowid | t_policy_change | 1 | 14 | 2 (50) | * 21 | index unique scan | pk_t_policy_change | 1 | 1 (0) | 22 | table access by index rowid | t_contract_master | 1 | 22 | 2 (50) | * 23 | index unique scan | pk_t_contract_master | 1 | 1 (0) | * 24 | filter | * 25 | connect by with filtering | 26 | nested loops | * 27 | index unique scan | pk_t_company_organ | 1 | 6 | 28 | table access by user rowid | t_company_organ | 29 | nested loops | 30 | buffer sort | 7 | 70 | 31 | connect by pump | * 32 | index range scan | t_company_organ_idx_002 | 7 | 70 | 1 (0) | inclupredicate information (identified by Operation ID): Limit 2-filter (exists (select/* + no_unnest */0 from "t_company_organ" "t_company_organ" where "t_company_organ ". "parent_id" = NULL and ("t_company_organ ". "organ_id" =: B1) 8-access ("sys_alias_1 ". "fee_type" = "C ". "type_id") 10-access ("sys_alias_1 ". "pay_mode" = "G ". "mode_id") 12-filter ("sys_alias_1 ". "change_id" is not null and "sys_alias_1 ". "fee_status" = 1 and "sys_alias_1 ". "payment_id" is null) 13-access ("sys_alias_1 ". "cmd_status" = '1') 15-access ("sys_alias_1 ". "policy_id" = "D ". "policy_id") 17-access ("D ". "company_id" = "E ". "company_id" (+) 19-access ("D ". "applicant_id" = "F ". "customer_id" (+) 21-access ("TPC ". "change_id" = "sys_alias_1 ". "change_id") 23-access ("TCM ". "policy_id" = "TPC ". "policy_id") 24-filter ("t_company_organ ". "organ_id" =: B1) 25-filter ("t_company_organ ". "organ_id" = '000000') 27-access ("t_company_organ ". "organ_id" = '000000') 32-access ("t_company_organ ". "parent_id" = NULL) 58 rows selected. statistics defaults 0 recursive cballs 0 dB block gets 2817 consistent gets 0 physical reads 0 redo size 2268 bytes sent via SQL * Net to client 656 bytes received via SQL * Net From Client 2 SQL * Net roundtrips to/from client 40 sorts (memory) 0 sorts (Disk) 9 rows processed

In the end, this SQL statement can run in less than 1 second, and the logical read is reduced to 2817. So far, I have not continued to optimize the SQL statement. At this time, I will stop optimizing the SQL statement. Other force-optimization problems will occur.
This optimization case is very simple. I am sorry to post it on my blog. What you need to learn through this article is that if the subquery returns very little data, you may wish to let it go through the filter

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.