Home » SQL & PL/SQL » SQL & PL/SQL » Query Rewriting - Assistance Needed (Oracle 11.2.0.4, Solaris 10 1/13)
Query Rewriting - Assistance Needed [message #649732] Tue, 05 April 2016 00:31 Go to next message
suddhasatwa_oracle
Messages: 24
Registered: January 2014
Junior Member
Hello All,

I have a requirement wherein from my transactions database, I would need to print some columns from 2/3 tables related to a particular package which is being sold by the organisation. To do so, however, we need to take the max or latest transaction ID or latest transaction date for calculations.

To write this, I have written the below query (table names changed intentionally), which is looking at the data only for one package for last 90 days. However, it is still posing much slowness, so I believe I have not written it well.

Kindly advise on how this can be made better in terms of execution.

Regards,
Suddhasatwa

SELECT
  /*+ index(trans idx6_rpt_transaction_status)
  index(trans idx3_rpt_transaction) index(sub idx3_rpt_subscription)
  index(sub idx4_rpt_subscription) */
  SUB.PACKAGE_ID,
  TRANS.USER_GROUP,
  TRANS.AMOUNT,
  TRANS.PROMO_CODE,
  SUB.STATUS_OBJ_ID,
  COUNT(DISTINCT ACC.ACCOUNT_OBJ_ID) AS DISTINCT_USERS
FROM TRANSACTION_TABLE TRANS,
  SUBSCRIPTION_TABLE SUB,
  ACCOUNT_TABLE ACC,
  COUNTRY_TABLE country_main
WHERE ( SUB.COUNTRY_CODE                 =ACC.COUNTRY_CODE
AND SUB.SYSTEM_NAME                      =ACC.SYSTEM_NAME
AND SUB.ACCOUNT_OBJ_ID                   =ACC.ACCOUNT_OBJ_ID )
AND ( TRANS.COUNTRY_CODE                 =SUB.COUNTRY_CODE
AND TRANS.SYSTEM_NAME                    =SUB.SYSTEM_NAME
AND TRANS.SUBSCRIPTION_OBJ_ID            =SUB.SUBSCRIPTION_OBJ_ID )
AND ( country_main.COUNTRY_CODE          =ACC.COUNTRY_CODE )
AND ( SUB.STATUS_OBJ_ID                 IN (1,4))
AND country_main.COUNTRY_CODE            = 2
AND SUB.PACKAGE_ID                       = 'p523tvpre1_W'
AND TRANS.AMOUNT                        <> 1.49
AND SUBSTR(country_main.ISO_COUNTRY,0,2) = 'DE'
AND TRANS.TRANSACTION_TYPE_OBJ_ID       IN ('2','4','5')
AND TRANS.resource_obj_id               <> 6
AND TRANS.PROMO_CODE                    IN ('TRIAL','*')
AND TRANS.USER_GROUP                     = '*'
AND TRANS.AMOUNT                        IN (0,0.99)
AND TRANS.PAYMENT_TRANS_OBJ_ID IN
  (SELECT
    /*+ index(tra idx6_rpt_transaction_status) index(tra idx3_rpt_transaction)
    index(subs idx3_rpt_subscription) index(subs idx4_rpt_subscription) */
    MAX(TRA.PAYMENT_TRANS_OBJ_ID)
  FROM TRANSACTION_TABLE TRA,
    SUBSCRIPTION_TABLE SUBS,
    ACCOUNT_TABLE AC
  WHERE SUBS.COUNTRY_CODE     =AC.COUNTRY_CODE
  AND SUBS.SYSTEM_NAME        =AC.SYSTEM_NAME
  AND SUBS.ACCOUNT_OBJ_ID     =AC.ACCOUNT_OBJ_ID
  AND TRA.COUNTRY_CODE        =SUBS.COUNTRY_CODE
  AND TRA.SYSTEM_NAME         =SUBS.SYSTEM_NAME
  AND TRA.SUBSCRIPTION_OBJ_ID =SUBS.SUBSCRIPTION_OBJ_ID
    --AND SUBS.PACKAGE_ID              = 'p523tvpre1_W'
  AND AC.ACCOUNT_OBJ_ID = ACC.ACCOUNT_OBJ_ID
    --AND SUBS.STATUS_OBJ_ID                 IN (1,4)
    --AND TRANS.AMOUNT                <> 1.49
    --AND TRA.COUNTRY_CODE             = 2
    --AND TRA.TRANSACTION_TYPE_OBJ_ID IN ('2','4','5')
    --AND TRA.resource_obj_id         <> 6
    --AND TRA.PROMO_CODE              IN ('TRIAL','*')
    --AND TRA.USER_GROUP               = '*'
    --AND TRA.AMOUNT                  IN (0,0.99)
    --AND TRA.CREATED_DATE < sysdate - 30
    AND TRA.ER_CREATED_DATE > sysdate - 60
  GROUP BY AC.ACCOUNT_OBJ_ID
  )
-- AND TRANS.ER_CREATED_DATE > sysdate - 90
GROUP BY SUB.PACKAGE_ID,
  TRANS.USER_GROUP,
  TRANS.AMOUNT,
  TRANS.PROMO_CODE,
  SUB.STATUS_OBJ_ID ;
Re: Query Rewriting - Assistance Needed [message #649736 is a reply to message #649732] Tue, 05 April 2016 01:06 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
Someone has inserted hints that are meaningless. They attempt to tell Oracle to use two indexes for one table, which is not possible. Does it run better if you remove them?
Re: Query Rewriting - Assistance Needed [message #649738 is a reply to message #649736] Tue, 05 April 2016 01:38 Go to previous messageGo to next message
JNagtzaam
Messages: 36
Registered: July 2015
Location: Alkmaar
Member

We can't tell if you don't deliver the explain plan output. But I suspect, there is no index on TRANSACTION_TABLE.CREATED_DATE. And if there was, it is probably not used because of the (wrong) hints ...
Re: Query Rewriting - Assistance Needed [message #649744 is a reply to message #649738] Tue, 05 April 2016 02:38 Go to previous messageGo to next message
suddhasatwa_oracle
Messages: 24
Registered: January 2014
Junior Member
I have revised the query as under :

WITH max_transaction_id AS
  (SELECT
    MAX(TRA.PAYMENT_TRANS_OBJ_ID) AS PAYMENT_TRANS_OBJ_ID
  FROM TRANSACTION_TABLE TRA,
    SUBSCRIPTION_TABLE SUBS,
    RS_RPT_ACCOUNT AC
  WHERE SUBS.COUNTRY_CODE          =AC.COUNTRY_CODE
  AND SUBS.SYSTEM_NAME             =AC.SYSTEM_NAME
  AND SUBS.ACCOUNT_OBJ_ID          =AC.ACCOUNT_OBJ_ID
  AND TRA.COUNTRY_CODE             =SUBS.COUNTRY_CODE
  AND TRA.SYSTEM_NAME              =SUBS.SYSTEM_NAME
  AND TRA.SUBSCRIPTION_OBJ_ID      =SUBS.SUBSCRIPTION_OBJ_ID
  AND SUBS.PACKAGE_ID              = 'p523tvpre1_W'
  AND SUBS.STATUS_OBJ_ID          IN (1,4)
  AND TRA.AMOUNT                <> 1.49
  AND TRA.COUNTRY_CODE             = 2
  AND TRA.TRANSACTION_TYPE_OBJ_ID IN ('2','4','5')
  AND TRA.resource_obj_id         <> 6
  AND TRA.PROMO_CODE              IN ('TRIAL','*')
  AND TRA.USER_GROUP               = '*'
  AND TRA.AMOUNT                            IN (0,0.99)
  AND TRA.ER_CREATED_DATE          > sysdate - 60
  GROUP BY AC.ACCOUNT_OBJ_ID
  )
SELECT
  SUB.PACKAGE_ID,
  TRANS.USER_GROUP,
  TRANS.AMOUNT,
  TRANS.PROMO_CODE,
  SUB.STATUS_OBJ_ID,
  COUNT(DISTINCT ACC.ACCOUNT_OBJ_ID) AS DISTINCT_USERS
FROM TRANSACTION_TABLE TRANS,
  SUBSCRIPTION_TABLE SUB,
  RS_RPT_ACCOUNT ACC,
  COUNTRY_TABLE country_main
WHERE ( SUB.COUNTRY_CODE                 =ACC.COUNTRY_CODE
AND SUB.SYSTEM_NAME                      =ACC.SYSTEM_NAME
AND SUB.ACCOUNT_OBJ_ID                   =ACC.ACCOUNT_OBJ_ID )
AND ( TRANS.COUNTRY_CODE                 =SUB.COUNTRY_CODE
AND TRANS.SYSTEM_NAME                    =SUB.SYSTEM_NAME
AND TRANS.SUBSCRIPTION_OBJ_ID            =SUB.SUBSCRIPTION_OBJ_ID )
AND ( country_main.COUNTRY_CODE          =ACC.COUNTRY_CODE )
AND ( SUB.STATUS_OBJ_ID                 IN (1,4))
AND country_main.COUNTRY_CODE            = 2
--AND SUB.PACKAGE_ID                       = 'p523tvpre1_W'
AND TRANS.AMOUNT                        <> 1.49
AND SUBSTR(country_main.ISO_COUNTRY,0,2) = 'DE'
AND TRANS.TRANSACTION_TYPE_OBJ_ID       IN ('2','4','5')
AND TRANS.resource_obj_id               <> 6
AND TRANS.PROMO_CODE                    IN ('TRIAL','*')
AND TRANS.USER_GROUP                     = '*'
AND TRANS.AMOUNT                        IN (0,0.99)
AND TRANS.PAYMENT_TRANS_OBJ_ID          IN
  (SELECT DISTINCT PAYMENT_TRANS_OBJ_ID
  FROM max_transaction_id
  )
AND TRANS.ER_CREATED_DATE > sysdate - 90
GROUP BY SUB.PACKAGE_ID,
  TRANS.USER_GROUP,
  TRANS.AMOUNT,
  TRANS.PROMO_CODE,
  SUB.STATUS_OBJ_ID ;


The explain plan is as under:

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2423280418

-------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                      | Name                     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                               |                          |     1 |    40 |    13  (16)| 00:00:01 |       |       |
|   1 |  HASH GROUP BY                                 |                          |     1 |    40 |    13  (16)| 00:00:01 |       |       |
|   2 |   VIEW                                         | VM_NWVW_2                |     1 |    40 |    13  (16)| 00:00:01 |       |       |
|   3 |    HASH GROUP BY                               |                          |     1 |   121 |    13  (16)| 00:00:01 |       |       |
|   4 |     NESTED LOOPS                               |                          |     1 |   121 |    12   (9)| 00:00:01 |       |       |
|   5 |      NESTED LOOPS                              |                          |     1 |   107 |    12   (9)| 00:00:01 |       |       |
|   6 |       NESTED LOOPS                             |                          |     1 |    70 |    10  (10)| 00:00:01 |       |       |
|   7 |        NESTED LOOPS                            |                          |     1 |    27 |     7  (15)| 00:00:01 |       |       |
|*  8 |         INDEX RANGE SCAN                       | IX_RS_COUNTRY_03         |     1 |    14 |     1   (0)| 00:00:01 |       |       |
|   9 |         VIEW                                   | VW_NSO_1                 |     1 |    13 |     6  (17)| 00:00:01 |       |       |
|  10 |          SORT UNIQUE                           |                          |     1 |    94 |     6  (17)| 00:00:01 |       |       |
|  11 |           SORT GROUP BY                        |                          |     1 |    94 |     6  (17)| 00:00:01 |       |       |
|  12 |            NESTED LOOPS                        |                          |     1 |    94 |     5   (0)| 00:00:01 |       |       |
|  13 |             NESTED LOOPS                       |                          |     1 |    80 |     5   (0)| 00:00:01 |       |       |
|  14 |              PARTITION RANGE ITERATOR          |                          |     1 |    43 |     3   (0)| 00:00:01 |   KEY |   113 |
|* 15 |               TABLE ACCESS BY LOCAL INDEX ROWID| RS_RPT_TRANSACTION       |     1 |    43 |     3   (0)| 00:00:01 |   KEY |   113 |
|* 16 |                INDEX RANGE SCAN                | IX_RS_RPT_TRANSACTION_03 |     1 |       |     2   (0)| 00:00:01 |   KEY |   113 |
|* 17 |              TABLE ACCESS BY INDEX ROWID       | RS_RPT_SUBSCRIPTION      |     1 |    37 |     2   (0)| 00:00:01 |       |       |
|* 18 |               INDEX UNIQUE SCAN                | PK_RPT_SUBSCRIPTION      |     1 |       |     1   (0)| 00:00:01 |       |       |
|* 19 |             INDEX UNIQUE SCAN                  | PK_RPT_ACCOUNT           |     1 |    14 |     0   (0)| 00:00:01 |       |       |
|* 20 |        TABLE ACCESS BY GLOBAL INDEX ROWID      | RS_RPT_TRANSACTION       |     1 |    43 |     3   (0)| 00:00:01 | ROWID | ROWID |
|* 21 |         INDEX RANGE SCAN                       | PK_RS_RPT_TRANSACTION    |     1 |       |     2   (0)| 00:00:01 |       |       |
|* 22 |       TABLE ACCESS BY INDEX ROWID              | RS_RPT_SUBSCRIPTION      |     2 |    74 |     2   (0)| 00:00:01 |       |       |
|* 23 |        INDEX UNIQUE SCAN                       | PK_RPT_SUBSCRIPTION      |     1 |       |     1   (0)| 00:00:01 |       |       |
|* 24 |      INDEX UNIQUE SCAN                         | PK_RPT_ACCOUNT           |     1 |    14 |     0   (0)| 00:00:01 |       |       |
-------------------------------------------------------------------------------------------------------------------------------------------

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

   8 - access("COUNTRY_MAIN"."COUNTRY_CODE"=2)
       filter(SUBSTR("COUNTRY_MAIN"."ISO_COUNTRY",0,2)='DE')
  15 - filter(("TRA"."AMOUNT"=0 OR "TRA"."AMOUNT"=0.99) AND "TRA"."RESOURCE_OBJ_ID"<>6 AND ("TRA"."TRANSACTION_TYPE_OBJ_ID"=2 OR
              "TRA"."TRANSACTION_TYPE_OBJ_ID"=4 OR "TRA"."TRANSACTION_TYPE_OBJ_ID"=5) AND "TRA"."USER_GROUP"='*' AND ("TRA"."PROMO_CODE"='*' OR
              "TRA"."PROMO_CODE"='TRIAL') AND "TRA"."AMOUNT"<>1.49)
  16 - access("TRA"."ER_CREATED_DATE">SYSDATE@!-60 AND "TRA"."COUNTRY_CODE"=2 AND "TRA"."ER_CREATED_DATE" IS NOT NULL)
       filter("TRA"."COUNTRY_CODE"=2)
  17 - filter("SUBS"."PACKAGE_ID"='p523tvpre1_W' AND ("SUBS"."STATUS_OBJ_ID"=1 OR "SUBS"."STATUS_OBJ_ID"=4))
  18 - access("SUBS"."COUNTRY_CODE"=2 AND "TRA"."SUBSCRIPTION_OBJ_ID"="SUBS"."SUBSCRIPTION_OBJ_ID" AND
              "TRA"."SYSTEM_NAME"="SUBS"."SYSTEM_NAME")
  19 - access("AC"."COUNTRY_CODE"=2 AND "SUBS"."ACCOUNT_OBJ_ID"="AC"."ACCOUNT_OBJ_ID" AND "SUBS"."SYSTEM_NAME"="AC"."SYSTEM_NAME")
  20 - filter(("TRANS"."AMOUNT"=0 OR "TRANS"."AMOUNT"=0.99) AND "TRANS"."RESOURCE_OBJ_ID"<>6 AND
              ("TRANS"."TRANSACTION_TYPE_OBJ_ID"=2 OR "TRANS"."TRANSACTION_TYPE_OBJ_ID"=4 OR "TRANS"."TRANSACTION_TYPE_OBJ_ID"=5) AND
              "TRANS"."ER_CREATED_DATE">SYSDATE@!-90 AND "TRANS"."USER_GROUP"='*' AND ("TRANS"."PROMO_CODE"='*' OR "TRANS"."PROMO_CODE"='TRIAL')
              AND "TRANS"."AMOUNT"<>1.49)
  21 - access("TRANS"."COUNTRY_CODE"=2 AND "TRANS"."PAYMENT_TRANS_OBJ_ID"="PAYMENT_TRANS_OBJ_ID")
  22 - filter("SUB"."STATUS_OBJ_ID"=1 OR "SUB"."STATUS_OBJ_ID"=4)
  23 - access("SUB"."COUNTRY_CODE"=2 AND "TRANS"."SUBSCRIPTION_OBJ_ID"="SUB"."SUBSCRIPTION_OBJ_ID" AND
              "TRANS"."SYSTEM_NAME"="SUB"."SYSTEM_NAME")
  24 - access("ACC"."COUNTRY_CODE"=2 AND "SUB"."ACCOUNT_OBJ_ID"="ACC"."ACCOUNT_OBJ_ID" AND "SUB"."SYSTEM_NAME"="ACC"."SYSTEM_NAME")

Re: Query Rewriting - Assistance Needed [message #649745 is a reply to message #649744] Tue, 05 April 2016 02:58 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
More than likely your statistics are rubbish. Do a few checks. For example, how many rows does this filter at operation 15 return -
select count(*) from RS_RPT_TRANSACTION tra 
where"TRA"."ER_CREATED_DATE">SYSDATE@!-60 AND "TRA"."COUNTRY_CODE"=2 AND "TRA"."ER_CREATED_DATE" IS NOT NULL;

Oracle thinks there is only one row.

--update, sorry, operation 16, not 15.

[Updated on: Tue, 05 April 2016 02:58]

Report message to a moderator

Re: Query Rewriting - Assistance Needed [message #649752 is a reply to message #649745] Tue, 05 April 2016 04:30 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
Did you generate that explain plan on the DB where the query is running slow or on a DEV box with no data?
It needs to be on the slow DB. If it was, then as John says the stats are rubbish and need to be regathered.
Re: Query Rewriting - Assistance Needed [message #649771 is a reply to message #649752] Wed, 06 April 2016 00:12 Go to previous messageGo to next message
suddhasatwa_oracle
Messages: 24
Registered: January 2014
Junior Member
I have generated the plan on the slow DB itself, which unfortunately is our production!

as from your advise above and from the investigations I did with the DBA, it is clear that the statistics are not being generated properly, although the DBA confirms that we have the AUTO DBMS_JOB running for gathering statistics - the one which comes out of the box by default.

I am not sure why above is the case, however, irrespective of the statistics part of it, which our DBA would be looking at, could you kindly advise what I could do as a developer to make sure my query is even better? Is there a way I can re-write it for even better execution?

Kindly advise.

Regards,
Suddhasatwa
Re: Query Rewriting - Assistance Needed [message #649772 is a reply to message #649771] Wed, 06 April 2016 01:23 Go to previous message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
You need to discuss this further with your DBA. In your release of the database, statistics are (or should be) gathered by the autotask system, certainly not by DBMS_JOB. Perhaps he is looking in the wring place. And in the meantime, I would do this:
exec dbms_stats.gather_database_stats(estimate_percent=>100,method_opt=>'for all columns size skewonly')

You'll need to gather dictionary stats, fixed object stats, and system stats too. I'll leave you to work out the syntax for that.
Previous Topic: Dynamically add alias to column name for a view.
Next Topic: XMLAGG issue
Goto Forum:
  


Current Time: Fri Apr 26 08:00:33 CDT 2024