Home » RDBMS Server » Performance Tuning » how to make it faster
how to make it faster [message #181796] Tue, 11 July 2006 09:30 Go to next message
mape
Messages: 298
Registered: July 2006
Location: Slovakia
Senior Member
Hello

I have this query and takes a long time.
Does anybody know how to rewrite this query?
Or how to split this query to smallest selects?

thanks a lot

----------------------------------------------------------------
SELECT /*+ ALL_ROWS */
       su.x_external_id || CHR (9) || ofr.x_offer_id
  FROM table_site_part su, table_site_part svc, table_x_csr_offer_cfg ofr
 WHERE svc.site_part2site_part = su.objid
   AND ofr.x_offer_id <> '457021455'
   AND ofr.x_csr_offer_cfg2service = svc.site_part2part_info
   AND ofr.x_export_event = 1
   AND su.x_site_part2status_su = 268488358
   AND EXISTS (
          SELECT 'X'
            FROM table_bus_org cu, table_site eu, table_site_part su
           WHERE su.site_part2site = eu.objid
             AND eu.x_site2customer = cu.objid
             AND cu.x_bus_org2billcycle BETWEEN 268442453 AND 268442456
          UNION ALL
          SELECT 'X'
            FROM table_bus_org cu, table_site eu, table_site_part su
           WHERE su.site_part2site = eu.objid
             AND eu.x_site2customer = cu.objid
             AND cu.x_bus_org2billcycle = 268451297)
   AND (   ofr.x_tariff_sensitive = 0
        OR (       ofr.x_tariff_sensitive = 1
               AND ofr.x_csr_offer_cfg2tariff =
                      (SELECT x_tariff_detail2tariff
                         FROM table_x_tariff_detail
                        WHERE x_tarif_detail2site_part = su.objid
                          AND x_active = 1)
            OR (    ofr.x_tariff_sensitive = 1
                AND ofr.x_csr_offer_cfg2tariff IS NULL
                AND NOT EXISTS (
                       SELECT 'X'
                         FROM table_x_csr_offer_cfg ofr2,
                              table_site_part su,
                              table_site_part svc,
                              table_x_tariff_detail td
                        WHERE svc.site_part2part_info =
                                                  ofr2.x_csr_offer_cfg2service
                          AND ofr2.x_tariff_sensitive = 1
                          AND su.objid = td.x_tarif_detail2site_part
                          AND td.x_active = 1
                          AND ofr2.x_csr_offer_cfg2tariff =
                                                     td.x_tariff_detail2tariff
                          AND ofr2.x_tariff_sensitive = td.x_active)
               )
           )
       )
   AND (   ofr.x_param_sensitive = 0
        OR EXISTS (
              SELECT 'X'
                FROM table_fa_site_part par, table_x_csr_param_value pv
               WHERE par.fa_site_part2site_part = svc.objid
                 AND par.fa_site_part2flex_defn = ofr.x_param_def_objid
                 AND pv.objid = ofr.x_csr_offer_cfg2par_value
                 AND par.attribute_value = pv.x_value)
       )
   AND (   svc.x_site_part2status_su = 805307984
        OR (    svc.x_site_part2status_su = 805307985
            AND ofr.x_suspend_sensitive = 0
           )
       )

----------------------------------------------------------------
  • Attachment: 1.sql
    (Size: 2.75KB, Downloaded 1508 times)

[Updated on: Tue, 11 July 2006 11:26]

Report message to a moderator

Re: how to make it faster [message #181828 is a reply to message #181796] Tue, 11 July 2006 14:58 Go to previous messageGo to next message
wagnerch
Messages: 58
Registered: July 2006
Member
Perhaps you should look at folding the subqueries into the main body of the query. Additionally it is a bit difficult for anyone to give you advice beyond that without knowning a few things like:

a) what are the data types involved, i see a few places where you are using character literals and numeric literals. if your literals are actually using a numeric or character field then the database will do a conversion -- it may decide to do a TO_CHAR(x_offer_id) and invalidate the index.
b) what size are the tables
c) what is indexed
d) what is the relationship (1:many, 1:1, etc)
e) how long is long
f) what does the plan look like


In any event I would start with trying to fold the subqueries into the main body. I tend to believe that someone made that query far more complicated then it needed to be.
Re: how to make it faster [message #181835 is a reply to message #181796] Tue, 11 July 2006 16:14 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
As was said, there is much information needed to correctly diagnose any problems. That said I note two things you might take interest in:

1) some of your correlated sub-queries don't make references back to tables in you main query. This might be correct, but might also indicate a correlated sub-query that is incorrectly written. Check those exists clauses to see if maybe you should be referring to one or more of the tables in your main query. As it is now, you have to basically scan all rows in these tables for every row considered by your main query. If indeed these correlated sub-queries are correct, then note that their answer will never change regardless of how many times they are executed and what row the main query is processing at any moment, so rewrite the query to pull these existential queries out (possibly with creative use of the WITH clause or nested selects in the from clause), and thus maybe save lots of time.

2) you use the ALL_ROWS hint. Get rid of it or find out why it is there. Additionally consider making some other changes to the query understanding that you could add the following tests to the where clause without changing the final result, but making it more clear where indexing might be of use...

and svc.x_site_part2status_su in (805307984,805307985)
and ofr.x_tariff_sensitive in (0,1)

If you don't understand why adding these will not change the results then look again. If you do understand then get yourself a query plan and do some data analysis to see if any of these phrases would dramatically limit the number of rows early on in your query. If so, get an index on the columns to support this.

I suspect there may be several things "wrong" with the query and thus there should be ample opportunity for improvement, good luck, Kevin
Re: how to make it faster [message #181836 is a reply to message #181796] Tue, 11 July 2006 16:15 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
Eliminate table_site_part svc out of the FROM clause
and subordinate it into the WHERE clause (use EXISTS),
because it contributes no values to the SELECT clause.
Re: how to make it faster [message #181868 is a reply to message #181796] Wed, 12 July 2006 00:26 Go to previous messageGo to next message
mape
Messages: 298
Registered: July 2006
Location: Slovakia
Senior Member
Hello

The biggest table is table_site_part. Its about 1 GBytes.
Other tables are smaller, about 10 Mbytes.
Relationship is 1:many unfortunately.
This query run almost 4 hours.

The HINT ALL_ROWS is the best choice by comparing in explain plan. Other HINT for example INDEX (su) does not help.


Here is the explain plan:
-----------------------------------------------------------------------------------------------
| Id  | Operation                       |  Name                       | Rows  | Bytes | Cost  |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                             | 37152 |  3301K|  1380 |
|   1 |  FILTER                         |                             |       |       |       |
|   2 |   FILTER                        |                             |       |       |       |
|   3 |    HASH JOIN                    |                             | 37152 |  3301K|  1380 |
|   4 |     TABLE ACCESS FULL           | TABLE_X_CSR_OFFER_CFG       |   116 |  5452 |     2 |
|   5 |     MERGE JOIN                  |                             |   118K|  5080K|  1354 |
|   6 |      TABLE ACCESS BY INDEX ROWID| TABLE_SITE_PART             |   284K|  7510K|   634 |
|   7 |       INDEX FULL SCAN           | IND_SITE_PART2SITE_PART     |   284K|       |    26 |
|   8 |      SORT JOIN                  |                             | 37012 |   614K|   720 |

|   9 |       TABLE ACCESS FULL         | TABLE_SITE_PART             | 37012 |   614K|   599 |
|  10 |    UNION-ALL                    |                             |       |       |       |
|  11 |     HASH JOIN                   |                             | 23248 |   612K|   512 |
|  12 |      HASH JOIN                  |                             | 35340 |   828K|   264 |
|  13 |       TABLE ACCESS FULL         | TABLE_BUS_ORG               |  4777 | 57324 |    48 |
|  14 |       TABLE ACCESS FULL         | TABLE_SITE                  |   137K|  1608K|   132 |
|  15 |      INDEX FAST FULL SCAN       | IND_SITE_PART_SITE          | 90301 |   264K|     3 |
|  16 |     HASH JOIN                   |                             | 21553 |   568K|   508 |
|  17 |      HASH JOIN                  |                             | 32765 |   767K|   264 |
|  18 |       TABLE ACCESS FULL         | TABLE_BUS_ORG               |  4429 | 53148 |    48 |
|  19 |       TABLE ACCESS FULL         | TABLE_SITE                  |   137K|  1608K|   132 |
|  20 |      INDEX FAST FULL SCAN       | IND_SITE_PART_SITE          | 90301 |   264K|     3 |
|  21 |   TABLE ACCESS BY INDEX ROWID   | TABLE_X_TARIFF_DETAIL       |     1 |    17 |     2 |

|  22 |    INDEX RANGE SCAN             | X_SU_TARIFF                 |     1 |       |     1 |
|  23 |   NESTED LOOPS                  |                             |   217M|  9965M|    42M|
|  24 |    NESTED LOOPS                 |                             | 20891 |   836K|    42M|
|  25 |     MERGE JOIN CARTESIAN        |                             |    21M|   480M|  1458 |
|  26 |      TABLE ACCESS FULL          | TABLE_X_CSR_OFFER_CFG       |    56 |   952 |     2 |
|  27 |      BUFFER SORT                |                             |   375K|  2564K|  1456 |
|  28 |       INDEX FULL SCAN           | SITE_PART_OBJINDEX          |   375K|  2564K|    26 |
|  29 |     TABLE ACCESS BY INDEX ROWID | TABLE_X_TARIFF_DETAIL       |     1 |    17 |     2 |
|  30 |      INDEX RANGE SCAN           | X_SU_TARIFF                 |     1 |       |     1 |
|  31 |    INDEX RANGE SCAN             | IND_SITE_PART2PART_INFO     | 10421 | 72947 |     1 |
|  32 |   NESTED LOOPS                  |                             |     1 |    31 |     3 |
|  33 |    TABLE ACCESS BY INDEX ROWID  | TABLE_X_CSR_PARAM_VALUE     |     1 |    11 |     1 |
|  34 |     INDEX UNIQUE SCAN           | X_CSR_PARAM_VALUE_OBJINDEX  |     1 |       |       |

|  35 |    TABLE ACCESS FULL            | TABLE_FA_SITE_PART          |     1 |    20 |     2 |
-----------------------------------------------------------------------------------------------



Anyway thanks for your help

Re: how to make it faster [message #182071 is a reply to message #181796] Wed, 12 July 2006 18:54 Go to previous message
wagnerch
Messages: 58
Registered: July 2006
Member
Based on your plan, lines 23 to 31 should be of a HUGE interest. It is producing a cartesian join, usually this would be caused by a missing join criteria. This inner query is the one producing the cartesian join:

SELECT 'X'
FROM table_x_csr_offer_cfg ofr2,
table_site_part su,
table_site_part svc,
table_x_tariff_detail td
WHERE svc.site_part2part_info =
ofr2.x_csr_offer_cfg2service
AND ofr2.x_tariff_sensitive = 1
AND su.objid = td.x_tarif_detail2site_part
AND td.x_active = 1
AND ofr2.x_csr_offer_cfg2tariff =
td.x_tariff_detail2tariff
AND ofr2.x_tariff_sensitive = td.x_active

The second problem with this inner query is it doesn't relate to an outer query, so it is full scanning all of the tables listed. I don't personally think it is doing what you want, and if it is then it is doing it in a VERY inefficient manner.

Clearly based on the plan, Oracle is estimating that this filter query is returning 217M rows and it is probably doing this 37152 times. Get rid of that subquery, or relate it to the other query.
Previous Topic: Performance Issue
Next Topic: Performance Issue
Goto Forum:
  


Current Time: Fri Apr 26 16:22:31 CDT 2024