Skip to Main Content

Oracle Database Discussions

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Avoiding full table scan on a large table in a query

orausernFeb 12 2013 — edited Feb 13 2013
Hi Experts,

I am on Oracle 11.2.0.2 on Solaris 10. I have an issue with one query that does a full table scan in a table that has 62k rows in development environment, and about 220k rows in FIT/QA environment. The query has a NOT EXISTS clause. I will be thankful on any pointers/suggestions on what can be done to tune the query. The table definition ddl, indexes etc, the query and the query plan are as follows:
CREATE TABLE TEST_CLIENT_APP
(
  APP_ID         VARCHAR2(50 BYTE)              NOT NULL,
  CLNT_OID       VARCHAR2(16 BYTE)              NOT NULL,
  CREATED_BY     VARCHAR2(80 BYTE),
  CREATED_DATE   DATE,
  MODIFIED_BY    VARCHAR2(80 BYTE),
  MODIFIED_DATE  DATE
);


CREATE TABLE TEST_MSG_USER
(
  MESSAGE_USER_ID           NUMBER(12)          NOT NULL,
  MESSAGE_INSTANCE_ID       NUMBER(12)          NOT NULL,
  CLNT_OID                  VARCHAR2(16 BYTE)   NOT NULL,
  PROCESS_STEP_ID           NUMBER(12),
  USER_OID                  VARCHAR2(16 BYTE)   NOT NULL,
  MESSAGE_STATUS            VARCHAR2(3 BYTE)    NOT NULL,
  SEND_REMINDER_DATE        DATE,
  SEND_REMINDER_COUNT       NUMBER(2),
  HIDE_DETAILS_LINK         NUMBER(1),
  ARCHIVED                  NUMBER(1)           NOT NULL,
  READ                      NUMBER(1)           NOT NULL,
  START_DATE                DATE                NOT NULL,
  END_DATE                  DATE,
  MESSAGE_TYPE_NAME         VARCHAR2(80 BYTE)   NOT NULL,
  BASE_TYPE                 CHAR(3 CHAR)        NOT NULL,
  GROUP_OID                 NUMBER(12),
  DUE_DATE                  DATE,
  REMINDER_TYPE             NUMBER(1),
  IS_DUE_DATE_SYS_ASSIGNED  NUMBER(1),
  TRACKED                   NUMBER(1)           NOT NULL
);


CREATE TABLE TEST_PROPERTIES
(
  PROPERTY_NAME           VARCHAR2(30 BYTE)     NOT NULL,
  CLIENT_OID              VARCHAR2(16 BYTE)     NOT NULL,
  PROPERTY_VALUE          VARCHAR2(1024 BYTE),
  APP_ID                  VARCHAR2(50 BYTE)     NOT NULL,
  PROPERTY_VALUE_LANG_ID  NUMBER(12)
);


CREATE UNIQUE INDEX PK_TEST_CLIENT_APP ON TEST_CLIENT_APP
(APP_ID, CLNT_OID);


CREATE UNIQUE INDEX PK_TEST_PROPERTIES ON TEST_PROPERTIES
(PROPERTY_NAME, CLIENT_OID);


CREATE INDEX TEST_MSG_USER_IDX01 ON TEST_MSG_USER
(USER_OID, MESSAGE_STATUS, CLNT_OID);


CREATE INDEX TEST_MSG_USER_IDX02 ON TEST_MSG_USER
(SEND_REMINDER_DATE);


CREATE INDEX TEST_MSG_USER_IDX03 ON TEST_MSG_USER
(PROCESS_STEP_ID);


CREATE INDEX TEST_MSG_USER_IDX04 ON TEST_MSG_USER
(CLNT_OID);


CREATE INDEX TEST_MSG_USER_IDX05 ON TEST_MSG_USER
(MESSAGE_TYPE_NAME);


CREATE INDEX TEST_MSG_USER_IDX06 ON TEST_MSG_USER
(MESSAGE_INSTANCE_ID);


CREATE INDEX TEST_MSG_USER_IDX07 ON TEST_MSG_USER
(CLNT_OID, USER_OID, MESSAGE_INSTANCE_ID);


ALTER TABLE TEST_CLIENT_APP ADD (
  CONSTRAINT PK_TEST_CLIENT_APP
  PRIMARY KEY
  (APP_ID, CLNT_OID)
  USING INDEX PK_TEST_CLIENT_APP
  ENABLE VALIDATE);


ALTER TABLE TEST_PROPERTIES ADD (
  CONSTRAINT PK_TEST_PROPERTIES
  PRIMARY KEY
  (PROPERTY_NAME, CLIENT_OID)
  USING INDEX PK_TEST_PROPERTIES
  ENABLE VALIDATE);

--following are the count of rows in these three tables:
SQL> select count(*) from test_msg_user;

  COUNT(*)
----------
     62701

SQL> select count(*) from test_properties;

  COUNT(*)
----------
         8

SQL> select count(*) from test_client_app;

  COUNT(*)
----------
       174


--the sql query is as follows:
variable SYS_B_1 VARCHAR2(30);
variable SYS_B_2 NUMBER;
variable SYS_B_3 VARCHAR2(30);
variable SYS_B_4 VARCHAR2(30);

											
exec :SYS_B_1:='COM' ;
exec :SYS_B_2:=180;
exec :SYS_B_3:='mcEnhanced';
exec :SYS_B_4:='true';


SELECT TMU.MESSAGE_USER_ID
  FROM    TEST_MSG_USER TMU
        WHERE TMU.ARCHIVED = 0 AND TMU.MESSAGE_STATUS = :SYS_B_1
       AND NOT EXISTS
                  (SELECT 1
                     FROM TEST_PROPERTIES tp, TEST_CLIENT_APP tca
                    WHERE     tp.app_id = tca.app_id
                          AND tp.property_name = :SYS_B_3
                          AND tp.property_value = :SYS_B_4
                          AND tca.CLNT_OID = TMU.CLNT_OID);

--Note the query returns 251 rows as output.
The query plan:
Plan hash value: 2291474835

----------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                    |       |       |   254 (100)|          |
|*  1 |  HASH JOIN RIGHT ANTI          |                    | 10223 |   409K|   254   (1)| 00:00:04 |
|   2 |   VIEW                         | VW_SQ_1            |     1 |    10 |     3   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                |                    |     1 |    59 |     3   (0)| 00:00:01 |
|*  4 |     TABLE ACCESS BY INDEX ROWID| TEST_PROPERTIES    |     1 |    33 |     2   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN          | PK_TEST_PROPERTIES |     1 |       |     1   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
|*  6 |     INDEX RANGE SCAN           | PK_TEST_CLIENT_APP |     7 |   182 |     1   (0)| 00:00:01 |
|*  7 |   TABLE ACCESS FULL            | TEST_MSG_USER      | 10450 |   316K|   251   (1)| 00:00:04 |
----------------------------------------------------------------------------------------------------

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

   1 - access("ITEM_1"="TMU"."CLNT_OID")
   4 - filter("TP"."PROPERTY_VALUE"=:SYS_B_4)
   5 - access("TP"."PROPERTY_NAME"=:SYS_B_3)
   6 - access("TP"."APP_ID"="TCA"."APP_ID")
   7 - filter(("TMU"."MESSAGE_STATUS"=:SYS_B_1 AND "TMU"."ARCHIVED"=:B0))


34 rows selected.
The issue is the full table scan on TEST_MSG_USER. Is there any way to avoid it?

Thanks,
OrauserN

Edited by: orausern on Feb 12, 2013 10:57 AM
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Mar 13 2013
Added on Feb 12 2013
12 comments
9,667 views