How to avoid full Table scan when using Rule based optimizer (Oracle817)

1. We have a Oracle 8.1.7 DB, and the optimizer_mode is set to "RULE"
2. There are three indexes on table cm_contract_supply, which is a large table having 28732830 Rows, and average row length 149 Bytes
COLUMN_NAME INDEX_NAME
PROGRESS_RECID XAK11CM_CONTRACT_SUPPLY
COMPANY_CODE XIE1CM_CONTRACT_SUPPLY
CONTRACT_NUMBER XIE1CM_CONTRACT_SUPPLY
COUNTRY_CODE XIE1CM_CONTRACT_SUPPLY
SUPPLY_TYPE_CODE XIE1CM_CONTRACT_SUPPLY
VERSION_NUMBER XIE1CM_CONTRACT_SUPPLY
CAMPAIGN_CODE XIF1290CM_CONTRACT_SUPPLY
COMPANY_CODE XIF1290CM_CONTRACT_SUPPLY
COUNTRY_CODE XIF1290CM_CONTRACT_SUPPLY
SUPPLIER_BP_ID XIF801CONTRACT_SUPPLY
COMMISSION_LETTER_CODE XIF803CONTRACT_SUPPLY
COMPANY_CODE XIF803CONTRACT_SUPPLY
COUNTRY_CODE XIF803CONTRACT_SUPPLY
COMPANY_CODE XPKCM_CONTRACT_SUPPLY
CONTRACT_NUMBER XPKCM_CONTRACT_SUPPLY
COUNTRY_CODE XPKCM_CONTRACT_SUPPLY
SUPPLY_SEQUENCE_NUMBER XPKCM_CONTRACT_SUPPLY
VERSION_NUMBER XPKCM_CONTRACT_SUPPLY
3. We are querying the table for a particular contract_number and version_number. We want to avoid full table scan.
SELECT /*+ INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
However despite of giving hint, query results are fetched after full table scan.
Execution Plan
0 SELECT STATEMENT Optimizer=RULE (Cost=1182 Card=1 Bytes=742)
1 0 TABLE ACCESS (FULL) OF 'CM_CONTRACT_SUPPLY' (Cost=1182 Card=1 Bytes=742)
4. I have tried giving
SELECT /*+ FIRST_ROWS + INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
and
SELECT /*+ CHOOSE + INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
But it does not work.
Is there some way without changing optimizer mode and without creating an additional index, we can use the index instead of full table scan?

David,
Here is my test on a Oracle 10g database.
SQL> create table mytable as select * from all_tables;
Table created.
SQL> set autot traceonly
SQL> alter session set optimizer_mode = choose;
Session altered.
SQL> select count(*) from mytable;
Execution Plan
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'MYTABLE' (TABLE)
Statistics
          1  recursive calls
          0  db block gets
         29  consistent gets
          0  physical reads
          0  redo size
        223  bytes sent via SQL*Net to client
        276  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL> analyze table mytable compute statistics;
Table analyzed.
SQL>  select count(*) from mytable
  2  ;
Execution Plan
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=11 Card=1)
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'MYTABLE' (TABLE) (Cost=11 Card=1
          788)
Statistics
          1  recursive calls
          0  db block gets
         29  consistent gets
          0  physical reads
          0  redo size
        222  bytes sent via SQL*Net to client
        276  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL> disconnect
Disconnected from Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options

Similar Messages

  • How can this query avoid full table scans?

    It is difficult to avoid full table scans in the following query because the values of column STATUS reiterant numbers. There are only 10 numbers values for the STATUS column (1..10)
    But the table is very large. there are more than 1 million rows in it. A full table scanning consumes too much time.
    How can this query avoid full table scans?
    Thank you
    SELECT SYNC,CUS_ID INTO V_SYNC,V_CUS_ID FROM CONSUMER_MSG_IDX
                      WHERE CUS_ID = V_TYPE_CUS_HEADER.CUS_ID AND
                            ADDRESS_ID = V_TYPE_CUS_HEADER.ADDRESS_ID AND
                            STATUS =! 8;Edited by: junez on Jul 23, 2009 7:30 PM

    Your code had an extra AND. I also replaced the "not equal" operator, which has display problems with the forum software
    SELECT SYNC,CUS_ID
       INTO V_SYNC,V_CUS_ID
      FROM CONSUMER_MSG_IDX
    WHERE CUS_ID = V_TYPE_CUS_HEADER.CUS_ID AND
           ADDRESS_ID = V_TYPE_CUS_HEADER.ADDRESS_ID AND
           STATUS != 8;Are you sure this query is doing a table scan? Is there an index on CUS_ID, ADDRESS_ID? I would think that would be mostly unique. So I'm not sure why you think the STATUS column is causing problems. It would seem to just be a non-selective additional filter.
    Justin

  • Avoid Full table scan

    Hi,
    My Query generation needs to be fine tuned. There are several queries generated that force full table scans of large tables. My question over here is whether functions and decodes need to be removed so that the queries take full advantage of the indexes on the table? I have used decode, Sum, case functions. So does it forces a full table scan of item price table (> 200 million records) as many times I have used these functions?
    How can I optimized it in more better way?

    How to see execution plan? Is it like explain plan you are saying? Can you please brief me on same.
    My query is
    Select S_ACCT_INFO.CUST_ACCT_NAM as CUST_ACCT_NAM,
           S_SLS_CRMEM_ITEM.CUST_ACCT_ID as CUST_ACCT_ID,
           S_SLS_CRMEM_ITEM.CUST_CNTRC_ID as CUST_CNTRC_ID,
           S_MCK_ITEM.GNRC_ID as GNRC_ID,
           S_MCK_ITEM.GNRC_NAM as GNRC_NAM,
           S_MCK_ITEM.SELL_DSCR_TXT as SELL_DSCR_TXT,
           S_MCK_ITEM.ITEM_STAT_CD_DSPSTN as ITEM_STAT_CD_DSPSTN,
           S_MCK_ITEM.RETL_LBL_CNT as RETL_LBL_CNT,
           S_MCK_ITEM.LBL_NAM as LBL_NAM,
           S_MCK_ITEM.MFG_SIZ_QTY as MFG_SIZ_QTY,
           S_SLS_CRMEM_ITEM.EM_ITEM_NUM as EM_ITEM_NUM,
           S_MCK_ITEM.NDC_NUM as NDC_NUM,
           S_MCK_ITEM.SPLR_ITEM_SEQ_NUM as SPLR_ITEM_SEQ_NUM,
           S_MCK_ITEM.SPLR_ACCT_NAM as SPLR_ACCT_NAM,
           S_MCK_ITEM.SPLR_ACCT_ID as SPLR_ACCT_ID,
           S_MCK_ITEM.UPC_NUM as UPC_NUM,
           S_IW_CNTRC_LEAD.CNTRC_LEAD_NAM as CNTRC_LEAD_NAM,
           DECODE(S_SLS_CRMEM_ITEM.CNTRC_LEAD_TP_ID, NULL, 'N', 'Y') CNTRC_IND_HIST,
           S_SLS_CRMEM_ITEM.CNTRC_LEAD_TP_ID as CNTRC_LEAD_TP_ID,
           S_SLS_CRMEM_ITEM.SLS_DOC_NUM as SLS_DOC_NUM,
           SUM(S_SLS_CRMEM_ITEM.SLS_AMT) INV_EXT_PRC_3,
           S_SLS_CRMEM_ITEM.SLS_PROC_WRK_DT as SLS_PROC_WRK_DT,
           CASE
             WHEN S_SLS_CRMEM_ITEM.GRS_SLS_QTY <> 0 THEN
              ROUND(S_SLS_CRMEM_ITEM.GRS_SLS_AMT / S_SLS_CRMEM_ITEM.GRS_SLS_QTY,
                    2)
             ELSE
              0
           END INV_PRC_PKG_2,
           SUM(S_SLS_CRMEM_ITEM.SLS_QTY) NET_QTY_3,
           S_SLS_CRMEM_ITEM.CUST_PO_NUM as CUST_PO_NUM,
           CASE
             WHEN S_SLS_CRMEM_ITEM.CUST_OMIT_IND IN
                  ('L', 'U', 'R', 'F', 'A', 'X') THEN
              SUM(S_SLS_CRMEM_ITEM.ORDR_QTY - S_SLS_CRMEM_ITEM.GRS_SLS_QTY)
             ELSE
              0
           END QTY_OMTD_MUS_1,
           S_ACCT_INFO.NATL_SUB_GRP_CD as NATL_SUB_GRP_CD,
           S_ACCT_INFO.CUST_STOR_NUM as CUST_STOR_NUM,
           S_MCK_ITEM.PKG_SIZ as PKG_SIZ,
           SUM(S_SLS_CRMEM_ITEM.GRS_SLS_QTY) INV_QTY_1,
           SUM(S_SLS_CRMEM_ITEM.ORDR_QTY) ORDR_QTY_2,
           SUM(S_SLS_CRMEM_ITEM.ORDR_QTY - S_SLS_CRMEM_ITEM.GRS_SLS_QTY) QTY_OMTD_1,
           SUM(S_SLS_CRMEM_ITEM.GRS_RTN_QTY) RTRN_QTY_1
      from S_SLS_CRMEM_ITEM
      LEFT OUTER JOIN S_MCK_ACCT_ITEM_PRC ON (S_SLS_CRMEM_ITEM.CUST_ACCT_ID =
                                             S_MCK_ACCT_ITEM_PRC.CUST_ACCT_ID AND
                                             S_SLS_CRMEM_ITEM.EM_ITEM_NUM =
                                             S_MCK_ACCT_ITEM_PRC.ITEM_NUM)
      LEFT OUTER JOIN S_ACCT_CNTRC_LEAD_TYP ON (S_MCK_ACCT_ITEM_PRC.CUST_ACCT_ID =
                                               S_ACCT_CNTRC_LEAD_TYP.CUST_ACCT_ID AND
                                               S_MCK_ACCT_ITEM_PRC.CNTRC_LEAD_ID =
                                               S_ACCT_CNTRC_LEAD_TYP.CNTRC_LEAD_ID)
      LEFT OUTER JOIN S_IW_CNTRC_LEAD ON (S_MCK_ACCT_ITEM_PRC.CNTRC_LEAD_ID =
                                         S_IW_CNTRC_LEAD.CNTRC_LEAD_ID)
    INNER JOIN S_ACCT_INFO ON (S_SLS_CRMEM_ITEM.CUST_ACCT_ID =
                               S_ACCT_INFO.CUST_ACCT_ID)
      LEFT OUTER JOIN S_VA_CUST_CNTRC ON (S_SLS_CRMEM_ITEM.CUST_ACCT_ID =
                                         S_VA_CUST_CNTRC.CUST_ACCT_ID AND
                                         S_SLS_CRMEM_ITEM.EM_ITEM_NUM =
                                         S_VA_CUST_CNTRC.ITEM_NUM)
    INNER JOIN S_MCK_ITEM ON (S_SLS_CRMEM_ITEM.EM_ITEM_NUM =
                              S_MCK_ITEM.EM_ITEM_NUM)
    where ((((((((S_SLS_CRMEM_ITEM.CUST_ACCT_ID in ('110718') or
           (S_ACCT_INFO.NATL_GRP_CD = '0227' and
           S_ACCT_INFO.NATL_SUB_GRP_CD = '000001')) or
           (S_ACCT_INFO.NATL_GRP_CD = '0227' and
           S_ACCT_INFO.NATL_SUB_GRP_CD = '000002')) or
           (S_ACCT_INFO.NATL_GRP_CD = '0227' and
           S_ACCT_INFO.NATL_SUB_GRP_CD = '000003')) or
           (S_ACCT_INFO.NATL_GRP_CD = '0227' and
           S_ACCT_INFO.NATL_SUB_GRP_CD = '000005')) or
           (S_ACCT_INFO.CUST_CHN_ID = '227' and
           S_ACCT_INFO.CUST_RGN_NUM = '000001')) or
           (S_ACCT_INFO.CUST_CHN_ID = '227' and
           S_ACCT_INFO.CUST_RGN_NUM = '000002')) or
           (S_ACCT_INFO.CUST_CHN_ID = '227' and
           S_ACCT_INFO.CUST_RGN_NUM = '000003')) or
           (S_ACCT_INFO.CUST_CHN_ID = '227' and
           S_ACCT_INFO.CUST_RGN_NUM = '000005'))
       and S_MCK_ITEM.SPLR_ACCT_ID IN
           ('34227', '34232', '34233', '34228', '34229', '34230', '34231',
            '34235', '34236', '78063', '84230', '90014', '98014')
       and (S_SLS_CRMEM_ITEM.SLS_PROC_WRK_DT between
           to_date('04/01/2007', 'MM/DD/YYYY') and
           to_date('06/30/2007', 'MM/DD/YYYY'))
    GROUP BY S_ACCT_INFO.CUST_ACCT_NAM,
              S_SLS_CRMEM_ITEM.CUST_ACCT_ID,
              S_SLS_CRMEM_ITEM.CUST_CNTRC_ID,
              S_MCK_ITEM.GNRC_ID,
              S_MCK_ITEM.GNRC_NAM,
              S_MCK_ITEM.SELL_DSCR_TXT,
              S_MCK_ITEM.ITEM_STAT_CD_DSPSTN,
              S_MCK_ITEM.RETL_LBL_CNT,
              S_MCK_ITEM.LBL_NAM,
              S_MCK_ITEM.MFG_SIZ_QTY,
              S_SLS_CRMEM_ITEM.EM_ITEM_NUM,
              S_MCK_ITEM.NDC_NUM,
              S_MCK_ITEM.SPLR_ITEM_SEQ_NUM,
              S_MCK_ITEM.SPLR_ACCT_NAM,
              S_MCK_ITEM.SPLR_ACCT_ID,
              S_MCK_ITEM.UPC_NUM,
              S_IW_CNTRC_LEAD.CNTRC_LEAD_NAM,
              DECODE(S_SLS_CRMEM_ITEM.CNTRC_LEAD_TP_ID, NULL, 'N', 'Y'),
              S_SLS_CRMEM_ITEM.CNTRC_LEAD_TP_ID,
              S_SLS_CRMEM_ITEM.SLS_DOC_NUM,
              S_SLS_CRMEM_ITEM.SLS_PROC_WRK_DT,
              CASE
                WHEN S_SLS_CRMEM_ITEM.GRS_SLS_QTY <> 0 THEN
                 ROUND(S_SLS_CRMEM_ITEM.GRS_SLS_AMT /
                       S_SLS_CRMEM_ITEM.GRS_SLS_QTY,
                       2)
                ELSE
                 0
              END,
              S_SLS_CRMEM_ITEM.CUST_PO_NUM,
              S_SLS_CRMEM_ITEM.CUST_OMIT_IND,
              S_ACCT_INFO.NATL_SUB_GRP_CD,
              S_ACCT_INFO.CUST_STOR_NUM,
              S_MCK_ITEM.PKG_SIZ
    order by S_MCK_ITEM.NDC_NUM               asc,
              S_SLS_CRMEM_ITEM.SLS_PROC_WRK_DT asc,
              S_SLS_CRMEM_ITEM.SLS_PROC_WRK_DT asc

  • URGENT HELP Required: Solution to avoid Full table scan for a PL/SQL query

    Hi Everyone,
    When I checked the EXPLAIN PLAN for the below SQL query, I saw that Full table scans is going on both the tables TABLE_A and TABLE_B
    UPDATE TABLE_A a
    SET a.current_commit_date =
    (SELECT MAX (b.loading_date)
    FROM TABLE_B b
    WHERE a.sales_order_id = b.sales_order_id
    AND a.sales_order_line_id = b.sales_order_line_id
    AND b.confirmed_qty > 0
    AND b.data_flag IS NULL
    OR b.schedule_line_delivery_date >= '23 NOV 2008')
    Though the TABLE_A is a small table having nearly 1 lakh records, the TABLE_B is a huge table, having nearly 2 and a half crore records.
    I created an Index on the TABLE_B having all its fields used in the WHERE clause. But, still the explain plan is showing FULL TABLE SCAN only.
    When I run the query, it is taking long long time to execute (more than 1 day) and each time I have to kill the session.
    Please please help me in optimizing this.
    Thanks,
    Sudhindra

    Check the instruction again, you're leaving out information we need in order to help you, like optimizer information.
    - Post your exact database version, that is: the result of select * from v$version;
    - Don't use TOAD's execution plan, but use
    SQL> explain plan for <your_query>;
    SQL> select * from table(dbms_xplan.display);(You can execute that in TOAD as well).
    Don't forget you need to use the {noformat}{noformat} tag in order to post formatted code/output/execution plans etc.
    It's also explained in the instruction.
    When was the last time statistics were gathered for table_a and table_b?
    You can find out by issuing the following query:select table_name
    , last_analyzed
    , num_rows
    from user_tables
    where table_name in ('TABLE_A', 'TABLE_B');
    Can you also post the results of these counts;select count(*)
    from table_b
    where confirmed_qty > 0;
    select count(*)
    from table_b
    where data_flag is null;
    select count(*)
    from table_b
    where schedule_line_delivery_date >= /* assuming you're using a date, and not a string*/ to_date('23 NOV 2008', 'dd mon yyyy');

  • Why  it is taking full table scan when index is available

    Hi all,
    I am facing a strange problem with index.
    I created index on a column like
    1. CREATE INDEX ASSETS_ARTIST_IDX2 ON ASSETS(artist).
    SELECT asset.artist AS NAME FROM ASSETS asset WHERE asset.artist LIKE 'J%'
    Explain Plan : INDEX RANGE SCAN
    2. CREATE INDEX ASSETS_ARTIST_IDX2 ON ASSETS(UPPER (TRANSLATE (artist, ',;:"', ' ')));
    SELECT asset.artist AS NAME FROM ASSETS asset WHERE UPPER (TRANSLATE (artist, ',;:"', ' ')) LIKE 'J%'
              Explain Plan : TABLE ACCESS FULL
    first time it is taking index range scan,but in second situation scaning full table.Please let me know how to avoid the full table scan.
    Regards,
    Rajasekhar

    Actually, I misseunderstood damorgan' s statement about NULL and OP did not provide table definition. So based on FTS I would say it is more likely column is NULLable, otherwise I would expect INDEX FAST SCAN:
    SQL> create table emp1 as select * from emp
      2  /
    Table created.
    SQL> create index emp1_idx1 on emp1(empno)
      2  /
    Index created.
    SQL> exec dbms_stats.gather_table_stats('SCOTT','EMP1');
    PL/SQL procedure successfully completed.
    SQL> desc emp1
    Name                                                                     Null?    Type
    EMPNO                                                                             NUMBER(4)
    ENAME                                                                             VARCHAR2(10)
    JOB                                                                               VARCHAR2(9)
    MGR                                                                               NUMBER(4)
    HIREDATE                                                                          DATE
    SAL                                                                               NUMBER(7,2)
    COMM                                                                              NUMBER(7,2)
    DEPTNO                                                                            NUMBER(2)
    SQL> explain plan for
      2  select empno
      3  from emp1 where UPPER(TRANSLATE(empno, ',;:"', ' ')) LIKE '7%'
      4  /
    Explained.
    SQL> @?\rdbms\admin\utlxpls
    PLAN_TABLE_OUTPUT
    Plan hash value: 2226897347
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |      |     1 |     4 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS FULL| EMP1 |     1 |     4 |     3   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    PLAN_TABLE_OUTPUT
       1 - filter(UPPER(TRANSLATE(TO_CHAR("EMPNO"),',;:"',' ')) LIKE '7%')
    13 rows selected.
    SQL> alter table emp1 modify empno not null
      2  /
    Table altered.
    SQL> explain plan for
      2  select empno
      3  from emp1 where UPPER(TRANSLATE(empno, ',;:"', ' ')) LIKE '7%'
      4  /
    Explained.
    SQL> @?\rdbms\admin\utlxpls
    PLAN_TABLE_OUTPUT
    Plan hash value: 2850860361
    | Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT |           |     1 |     4 |     1   (0)| 00:00:01 |
    |*  1 |  INDEX FULL SCAN | EMP1_IDX1 |     1 |     4 |     1   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    PLAN_TABLE_OUTPUT
       1 - filter(UPPER(TRANSLATE(TO_CHAR("EMPNO"),',;:"',' ')) LIKE '7%')
    13 rows selected.
    SQL> SY.

  • Not getting Cost information when using /*+ RULE */ in toad 9.5

    Hi,
    While optimizing a query when I am using /*+RULE */ in the query I am not getting any info for cost and cardinality.
    Can you tell me is the /*+RULE* / obsolete in oracle or what can be the reason.
    Help me..
    Thanks in advance.

    948707 wrote:
    Hi,
    While optimizing a query when I am using /*+RULE */ in the query I am not getting any info for cost and cardinality.
    Can you tell me is the /*+RULE* / obsolete in oracle or what can be the reason.
    Why are you using that hint?
    Aside from the fact that rule based optimization is obsolete, the optimiser can either do Rule based optimization or Cost based optimization. Why would you expect to get Cost based information when using Rule based optimization?
    Don't use such hints. Cost based optimization is far superior to rule based.

  • Source(oracle 11g) with oracle 8i using db link with full table scan

    Hi,
    I'm using oracle 8i version and i'm facing some issue  while using DBlinks.
    SourceDB1 I'm using oracle 8i(Source)
    select *  from tab1
    tabl where id in
    (select id from stab1@SourceDB1  where updt_seq_num > 167720 and work_grp_id in (2900,2901))
    For this, I could able to retrive the data.
    but, today we have migrated one of our source from oracle 8i to oracle 11G
    when I'm executing
    select *  from tab2
    tabl where id in
    (select id from stab2@SourceDB2  where updt_seq_num > 167720 and work_grp_id in (2900,2901))
    we couldn't able to retrive data as it's scaning full table scan.
    when oracle 8i source it's scanning using INDEX scan but if the source oracle 11 h it's scanning full table scan.
    Could you please advise how to resolve this issue for source oracle 11i ?
    Please let us know, if you need any information.

    Blocks that are read via full table scans are stored in the buffer cache, but putting them at the MRU end ensures that they don't push the rest of the useful blocks out of the buffer cache. In your example, if you're full scanning a 2 GB table (T) with a 500 MB buffer cache, the first block that is read from T is put at the MRU end of the buffer cache, displacing the previous block that was at the MRU end of the cache. The next block that is read from T is also put at the MRU end of the buffer cache, displacing the previous block that was at the MRU end of the cache, so block #2 from T displaces block #1 from T. So, you're reading 2 GB of data, but you're constantly purging the older blocks, so you're only really using that last block of the buffer cache.
    Justin

  • Tuning an insert sql that inserts a million rows doing a full table scan

    Hi Experts,
    I am on Oracle 11.2.0.3 on Linux. I have a sql that inserts data in a history/archive table from a main application table based on date. The application table has 3 million rows in it. and all rows that are older then 6 months should go into a history/archive table. this was recently decided and we have 1 million rows that satisfy this criteria. This insert into archive table is taking about 3 minutes. The explain plan shows a full table scan on the main table - which is the right thing as we are pulling out 1 million rows from main table into history table.
    My question is that, is there a way I can make this sql go faster?
    Here is the query plan (I changed the table names etc.)
       INSERT INTO EMP_ARCH
       SELECT *
    FROM EMP M
    where HIRE_date < (sysdate - :v_num_days);
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        2      0.00       0.00          0          0          0           0
    Execute      2     96.22     165.59      92266     147180    8529323     1441230
    Fetch        0      0.00       0.00          0          0          0           0
    total        4     96.22     165.59      92266     147180    8529323     1441230
    Misses in library cache during parse: 1
    Misses in library cache during execute: 1
    Optimizer mode: FIRST_ROWS
    Parsing user id: 166
    Rows     Row Source Operation
    1441401   TABLE ACCESS FULL EMP (cr=52900 pr=52885 pw=0 time=21189581 us)
    I heard that there is a way to use opt_param hint to increase the multiblock read count but didn't seem to work for me....I will be thankful for suggestions on this. also can collections and changing this to pl/sql make it faster?
    Thanks,
    OrauserN

    Also I wish experts share their insight on how we make full table scan go faster (apart from parallel suggestion I mean).
    Please make up your mind about what question you actually want help with.
    First you said you want help making the INSERT query go faster but the rest of your replies, including the above statement, imply that you are obsessed with making full table scans go faster.
    You also said:
    our management would like us to come forth with the best way to do it
    But when people make suggestions you make replies about you and your abilities:
    I do not have the liberty to do the "alter session enable parallel dml".  I have to work within this constraings
    Does 'management' want the best way to do whichever question you are asking?
    Or is is just YOU that want the best way (whatever you mean by best) based on some unknown set of constraints?
    As SB already said, you clearly do NOT have an actual problem since you have already completed the task of inserting the data, several times in fact. So the time it takes to do it is irrevelant.
    There is no universal agreement on what the word 'best' means for any given use case and you haven't given us your definition either. So how would we know what might be 'best'?
    So until you provide the COMPLETE list of constraints you are just wasting our time asking for suggestions that you refute with a comment about some 'constraint' you have.
    You also haven't provided ANY information that indicates that it is the full table scan that is the root of the problem. It is far more likely to be the INSERT into the table and a simple use of NOLOGGING with an APPEND hint might be all that is needed.
    IMHO the 'best' way would be to partition both the source and target tables and just use EXCHANGE PARTITION to move the data. That operation would only take a millisecond or two.
    But, let me guess, that would not conform to one of your 'unknown' constraints would it?

  • VARRAY bind parameter in IN clause causes Full Table Scan

    Hi
    My problem is that Oracle elects to perform a full table scan when I want it to use an index.
    The situation is this: I have a single table SQL query with an IN clause such as:
    SELECT EMPNO, ENAME, JOB FROM EMP WHERE ENAME IN (...)
    Since this is running in an application, I want to allow the user to provide a list of ENAMES to search. Because IN clauses don't accept bind parameters I've been using the Tom Kyte workaround which relies on setting a bind variable to an array-valued scalar, and then casting this array to be a table of records that the database can handle in an IN clause:
    SELECT *
    FROM EMP
    WHERE ENAME IN (
    SELECT *
    FROM TABLE(CAST( ? AS TABLE_OF_VARCHAR)))
    This resulted in very slow performance due to a full table scan. To test, I ran the SQL in SQL*Plus and provided the IN clause values in the query itself. The explain plan showed it using my index...ok good. But once I changed the IN clause to the 'select * from table...' syntax Oracle went into Full Scan mode. I added an index hint but it didn't change the plan. Has anyone had success using this technique without a full scan?
    Thanks
    John
    p.s.
    Please let me know if you think this should be posted on a different forum. Even though my context is a Java app developed with JDev this seemed like a SQL question.

    Justin and 3360 - that was great advice and certainly nothing I would have come up with. However, as posted, the performance still wasn't good...but it gave me a term to Google on. I found this Ask Tom page http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:3779680732446#15740265481549, where he included a seemingly magical 'where rownum >=0' which, when applied with your suggestions, turned my query from minutes into seconds.
    My plans are as follows:
    1 - Query with standard IN clause
    SQL> explain plan for
    2 select accession_number, protein_name, sequence_id from protein_dim
    3 where accession_number in ('33460', '33458', '33451');
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 7 | 336 | 4 |
    | 1 | INLIST ITERATOR | | | | |
    | 2 | TABLE ACCESS BY INDEX ROWID| PROTEIN_DIM | 7 | 336 | 4 |
    | 3 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 7 | | 3 |
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    11 rows selected.
    2 - Standard IN Clause with Index hint
    SQL> explain plan for
    2 select /*+ INDEX(protein_dim IDX_PROTEIN_ACCNUM) */
    3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
    4 from pdssuser.protein_dim
    5 where accession_number in
    6 ('33460', '33458', '33451');
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 7 | 588 | 4 |
    | 1 | INLIST ITERATOR | | | | |
    | 2 | TABLE ACCESS BY INDEX ROWID| PROTEIN_DIM | 7 | 588 | 4 |
    | 3 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 7 | | 3 |
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    11 rows selected.
    3 - Using custom TABLE_OF_VARCHAR type
    CREATE TYPE TABLE_OF_VARCHAR AS
    TABLE OF VARCHAR2(50);
    SQL> explain plan for
    2 select
    3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
    4 from pdssuser.protein_dim
    5 where accession_number in
    6 (select * from table(cast(TABLE_OF_VARCHAR('33460', '33458', '33451') as TABLE_OF_VARCHAR)) t);
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 2 | 168 | 57M|
    | 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
    | 2 | TABLE ACCESS FULL | PROTEIN_DIM | 5235K| 419M| 13729 |
    | 3 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    11 rows selected.
    4 - Using custom TABLE_OF_VARCHAR type w/ Index hint
    SQL> explain plan for
    2 select /*+ INDEX(protein_dim IDX_PROTEIN_ACCNUM) */
    3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
    4 from pdssuser.protein_dim
    5 where accession_number in
    6 (select * from table(cast(TABLE_OF_VARCHAR('33460', '33458', '33451') as TABLE_OF_VARCHAR)) t);
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 2 | 168 | 57M|
    | 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
    | 2 | TABLE ACCESS BY INDEX ROWID | PROTEIN_DIM | 5235K| 419M| 252K|
    | 3 | INDEX FULL SCAN | IDX_PROTEIN_ACCNUM | 5235K| | 17255 |
    | 4 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
    PLAN_TABLE_OUTPUT
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    12 rows selected.
    5 - Using custom TABLE_OF_VARCHAR type w/ cardinality hint
    SQL> explain plan for
    2 select
    3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source from protein_dim
    4 where accession_number in (select /*+ cardinality( t 10 ) */
    5 * from TABLE(CAST (TABLE_OF_VARCHAR('33460', '33458', '33451') AS TABLE_OF_VARCHAR)) t);
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 2 | 168 | 57M|
    | 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
    | 2 | TABLE ACCESS FULL | PROTEIN_DIM | 5235K| 419M| 13729 |
    | 3 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    11 rows selected.
    6 - Using custom TABLE_OF_VARCHAR type w/ cardinality hint
    and rownum >= 0 constraint
    SQL> explain plan for
    2 select
    3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source from protein_dim
    4 where accession_number in (select /*+ cardinality( t 10 ) */
    5 * from TABLE(CAST (TABLE_OF_VARCHAR('33460', '33458', '33451') AS TABLE_OF_VARCHAR)) t
    6 where rownum >= 0);
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 25 | 2775 | 43 |
    | 1 | TABLE ACCESS BY INDEX ROWID | PROTEIN_DIM | 2 | 168 | 3 |
    | 2 | NESTED LOOPS | | 25 | 2775 | 43 |
    | 3 | VIEW | VW_NSO_1 | 10 | 270 | 11 |
    | 4 | SORT UNIQUE | | 10 | | |
    | 5 | COUNT | | | | |
    | 6 | FILTER | | | | |
    PLAN_TABLE_OUTPUT
    | 7 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
    | 8 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 2 | | 2 |
    Note: cpu costing is off, 'PLAN_TABLE' is old version
    16 rows selected.
    I don't understand why performance improved so dramatically but happy that it did.
    Thanks a ton!
    John

  • Full table scans

    Dear all,
    While doing a stress testing I found that there was a lot a full table scans due to which there was preformance drop. How can I avoid full table scans. Please suggest some ways as I am in clients place.
    Waiting for your help.
    Regards and thanks in advance
    SL

    Hi SL,
    How can I avoid full table scansFull table scans are not always bad! It depends foremost on your optimizer goal (all_rows vs. first_rows), plus your multiblock read count, table size, percentage of rows requested, and many other factors.
    Here are my notes:
    http://www.dba-oracle.com/art_orafaq_oracle_sql_tune_table_scan.htm
    To avoid full table scans, start by running plan9i.sql and then drill-in and see if you have missing indexes:
    http://www.dba-oracle.com/t_plan9i_sql_full_table_scans.htm
    You can also run the 10g SQLTuning advisor to find missing indexes, and also, don't forget to consider function-based indexes, a great way to eliminate unncessary lage-table full-table scans:
    http://www.dba-oracle.com/oracle_tips_index_scan_fbi_sql.htm
    Hope this helps. . .
    Donald K. Burleson
    Oracle Press author

  • Theoretical Question about Full Table Scans

    Hi,
    how is a full table scan managed by the Oracle Server ?
    In my opinion, the blocks are put at the end of the LRU-list and are afterwards the first candidate to be swapped out.
    But if I have the case, that DB_BLOCK_BUFFERS is set to 500 MB and the table I scan via full table scan is 1 GB... how does Oracle handle this ?
    Is there a dependancy concerning table size ?
    Or does it bypass the buffer cache completely ?
    Any hint is welcome !
    Thx... Paul

    The Server Concepts manual is going to go into great detail here, but essentially what happens is that the blocks are put at the "least-recently-used" end of the buffer cache, so they're immediately swapped out.
    Justin

  • Data Federator Full Table scan

    Hi,
    Is it possible to prevent a Full table scan when creating a join between tables of 2 catalogues in a Data Federator?
    This is seriously hampering the development time within Data Federator Development.
    I am working with IDT Beta to create a Universe based on Multiple Source. The delay is so huge when creating joins that we could revert to Universe Design Tool. I have posted it here as Data Federator gurus will have tweak about IDT as it incorporates DF within itself in BI 4.0.
    Any inputs will be great.. In case this is in the wrong forums, then please move it accordingly.
    VFernandes

    The issue was fixed when the GA was released. This was present in Beta

  • How can I know the database is using Cost Based or Rule Based?

    Hi all expertise,
    How can I know the database is using Cost Based or Rule Based?
    If cost based it is using, what methods are need to use to minimize the cost when database is running? And which tables I can see the performance of the database?
    Thanks
    Amy

    how to see database setting ?
    use this
    SQL> sho parameter optimizer
    NAME TYPE VALUE
    optimizer_dynamic_sampling integer 1
    optimizer_features_enable string 9.2.0
    optimizer_index_caching integer 0
    optimizer_index_cost_adj integer 100
    optimizer_max_permutations integer 2000
    optimizer_mode string CHOOSE
    choose means if table statistics is available then it will use cost
    else
    use rule based optimizer
    for seeing performnace of table use
    set autotrace on
    and run your query
    if it doen't show cost.it means it use rule based
    for using cost based
    u will calculate table statistics
    9i
    dbms_stats.gather_table_stats('owner','table');
    8i
    analyze table <table_name> compute statistics;
    hope it will help you
    kuljeet pal singh

  • Full table scan and how to avoid it

    Hello,
    I have two tables, one with 425,000 records, and the other with 5,200,000 records in it. The smaller table has an index on its unique primary key, and the bigger table has an index on the foreign key of the smaller table.
    When joining these two tables, I keep getting full table scans on both of these tables, and I would like to understand the philosophy behind it as well as ways to avoid this.
    Thanks

    Are you manipulating the join columns in any fashion? Such as applying a function to them like in
    to_char(column_a) = to_char(column_b)Because any manipulation like that will obviate your index (assuming you don't have function based indexes).
    Really though, without your tables, indexes and query, we're left with voodoo, which is cool, but not really that effective.
    *note to any and all practicing witch doctors, i really do think voodoo is cool and effective, please don't persecute me for my speakings.
    Message was edited by:
    Tubby

  • How to check small table scan full table scan if we  will use index  in where clause.

    How to check small table scan full table scan if i will use index column in where clause.
    Is there example link there i can  test small table scan full table  if index is used in where clause.

    Use explain plan on your statement or set autotrace traceonly in your SQL*Plus session followed by the SQL you are testing.
    For example
    SQL> set autotrace traceonly
    SQL> select *
      2  from XXX
      3  where id='fga';
    no rows selected
    Execution Plan
       0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=13 Card=1 Bytes=16
              5)
       1    0   PARTITION RANGE (ALL) (Cost=13 Card=1 Bytes=165)
       2    1     TABLE ACCESS (FULL) OF 'XXX' (TABLE) (Cost=13 Card
              =1 Bytes=165)
    Statistics
              1  recursive calls
              0  db block gets
           1561  consistent gets
            540  physical reads
              0  redo size
           1864  bytes sent via SQL*Net to client
            333  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              0  rows processed

Maybe you are looking for