Berkeley DB C++ query on floating index

Im using Berkeley DB C++ API 6.0 on OSX. My application creates a database with the following tables:
Primary table: (int, myStruct) -> myStruct is a buffer.
Secondary index: (float, myStruct) -> The float key is an information that I retrieve in myStruct buffer with the following callback.
int meanExtractor(Db *sdbp, const Dbt *pkey, const Dbt *pdata, Dbt *skey) { Dbt data = *pdata; feature<float> f; restoreDescriptor(f, data); void* mean = malloc( sizeof(float) ); memcpy( mean, &f.mean, sizeof(float) ); skey->set_data(mean); skey->set_size(sizeof(float)); skey->set_flags( DB_DBT_APPMALLOC ); return 0; }
When I iterate over the secondary index and print the key/data pairs, the float keys are well stored. My problem is that I can't query this table. I would like to execute this SQL Query for example:
SELECT * FROM secondary index WHERE keys > 1.5 && keys < 3.4
My table is filled by 50000 keys between 0.001 and 49.999. The thing is when I use this method for example:
I assume the Db and the table are already opened float i = 0.05; Dbt key = Dbt(&i, sizeof(float)); Dbc* dbc; db->cursor( txn, &dbc, 0 ); int ret; ret = dbc->get( key, &vald, DB_SET_RANGE));
Its retrieved this key: 0.275. It should retrieve 0.05 (because it exists) or at least 0.051. And for any other floating value in the Dbt key, it gives me some stupid values. If I put the DB_SET flag, it just doesn't find any keys. My idea was to set the cursor to the smallest key greater than or equal to my key, and then to iterate with the flag DB_NEXT until I reach the end of my range.
This must come from the searching algorithm of BerkeleyDB but I saw some (usefull but not enough) examples that do exactly what I need but with the Java API, so it proves that is possible to do...
I'm pretty stucked with this one, so if anybody already had this problem before, thx for helping me. I can put other parts of my code if necessary.

Hi,
Since the default byte-comparison does not reflect the sort order of float numbers, have you set the bt_compare function for your secondary database ? From your description, your query relies on the correct float number sort order, so I think you should set a custom bt_compare function.
Also, as you do not do exact search, and just do range search, DBC->get(DB_SET) does not work for you. I think you need to use DB_SET_RANGE flag to get the nearest(just >=) item.  You can check the documentation for DBC(or Dbc in C++)  for more information.
Regards,
Winter, Oracle Berkeley DB

Similar Messages

  • Select query performance improvement - Index on EDIDC table

    Hi Experts,
    I have a scenario where in I have to select data from the table EDIDC. The select query being used is given below.
      SELECT  docnum
              direct
              mestyp
              mescod
              rcvprn
              sndprn
              upddat
              updtim
      INTO CORRESPONDING FIELDS OF TABLE t_edidc
      FROM edidc
      FOR ALL ENTRIES IN t_error_idoc
      WHERE
      upddat GE gv_date1 AND
      upddat LE gv_date2 AND
      updtim GE p_time AND
      status EQ t_error_idoc-status.
    As the volume of the data is very high, our client requested to put up some index or use an existing one to improve the performance of the data selection query.
    Question:
    4.    How do we identify the index to be used.
    5.    On which fields should the indexing be done to improve the performance (if available indexes donu2019t cater to our case).
    6.    What will be the impact on the table performance if we create a new index.
    Regards ,
    Raghav

    Question:
    1.    How do we identify the index to be used.
    Generally the index is automatically selected by SAP (DB Optimizer )  ( You can still mention the index name in your select query by changing the syntax)
      For your select Query the second Index will be called automatically by the Optimizer, ( Because  the select query has u2018Updatu2019 , u2018uptimu2019 in the sequence before the u2018statusu2019 ) .
    2.    On which fields should the indexing be done to improve the performance (if available indexes donu2019t cater to our case).
    (Create a new Index with MANDT and the 4 fields which are in the where clause in sequence  )
    3.    What will be the impact on the table performance if we create a new index.
    ( Since the index which will be newly created is only the 4th index for the table, there shouldnu2019t be any side affects)
    After creation of index , Check the change in performance of the current program and also some other programs which are having the select queries on EDIDC ( Various types of where clauses preferably ) to verify that the newly created index is not having the negative impact on the performance. Additionally, if possible , check if you can avoid  into corresponding fields .
    Regards ,
    Seth

  • Tuning OBIEE query with DB index, but it's getting slower

    Hello guys
    I just have a quick question about tuning the performance of sql query using bitmap indexes..
    Currently, there are 2 tables, date and fact. Fact table has about 1 billion row and date dim has about 1 million. These 2 tables are joined by 2 columns:
    Date.Dateid = Fact.snapshot.dates and Date.companyid = fact.companynumber
    I have query that needs to be run as the following:
    Select dates.dayofweek, dates,dates, fact.opened_amount from dates, facts
    where Date.Dateid = Fact.snapshot.dates and Date.companyid = fact.companynumber and dates.dayofweek = 'monday'.
    Currently this query is running forever. I think it is joining that takes a lot of time. I have created bitmap index on dayofweek column because it's low on distinctive rows. But it didn't seem to speed up with the performance, but rather made it worse. The explain plan before and after creating that index was the same as:
    Select statement optimizer
    nested loops
    partition list all
    index full scan RD_T.PK_FACTS_SNPSH
    TABLE ACCESS BY INDEX ROWID DATES_DIM
    INDEX UNIQUE SCAN DATES_DIM_DATE
    It seems the bitmap index I created for DATES_DIM wasn't used... Also, I am thinking what other indexes I should create for fact table..
    I'd like to know what other indexes will be helpful for me and on which table & columns?.. I am thinking of creating another one for companynumber since it also have low distinctive records.
    Currently I can't purge data or create smaller table, I have to what with what I have..
    So please let me know your thoughts in terms of performance tunings for such situation..
    Thanks

    Jack,
    Thank you for your response. It helped me to clean up the query. All the changes did not give a much better explain plan - at least not to my inexperienced eyes - but the total execution time for the query is now reduced to under two minutes. The query as it is now:
    select /*+ ordered all_rows */ x.rowid1
    from table(sdo_join('CYCLORAMA','GEOMETRIE','CYCLORAMA','GEOMETRIE','distance=3 mask=ANYINTERACT')) x
    , cyclorama s, cyclorama t
    where not x.rowid1 = x.rowid2
    and s.rowid = x.rowid1 and x.rowid2 = t.rowid
    and s.datasetid != t.datasetid
    and s.opnamedatum < t.opnamedatum;Because the docs state that mask=FILTER is the default, I added an explicit mask=ANYINTERACT to the sdo_join parameters when I removed the sdo_distance from the query. Still, the query returns 205035 records with the sdo_distance, and 205125 without. But this may be the result of the extra 0.001 from sdo_dim. I did not investigate as the 3 meter is not crucial.
    I believe I already had a mechanism in place to reduce the number of self-joins with "not x.rowid1 = x.rowid2" and "s.opnamedatum < t.opnamedatum". I can not guarantee that for all records s.opnamedatum < t.opnamedatum equals x.rowid1 < x.rowid2.
    Based on the [url http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_operat.htm#BGEDJIBF]docs, I finally added an 'ordered' hint and reshuffled the tables in the from clause.
    I'm happy with performance now, and creating a new table with the records to keep should not be a problem. Still I'm curious about the following:
    <li>Is it worth optimizing the SDO_DIM_ARRAY for the original table, e.g. narrowing the range of coordinate values?
    <li>How can sdo_join best be used for an anti-join, to select the records to keep?
    Thank you,
    J-----.

  • Query uses wrong index

    Hi,
    I have exported and imported two schemas to a different server. Now when a user fires a select query it takes more time than before. When I saw the execution plan for some of 'select' queries,I found that the queries are using wrong index.This is the reason for the delayed reponse time.
    Can anybody tell me why it happened ?
    Now what should I do?
    Can I force select query to use the right index?
    Thanx in advance

    Please find below details of the query and indexes. Do let me know if you need more information.
    Query:
    SELECT ROWID, warehouse_code, branch_code, client_code, job_srnum,
    department, inventory_date, file_no, client_carton_no, description,
    ref1, ref2, ref3, destruction_date, subject, pnw_carton_no,
    cre_user_id, cre_dt, upd_user_id, branch, upd_dt, status, date1,
    date2, num1, carton_size, addendum_date
    FROM ISTORET.rmst_inventory_details2
    WHERE branch_code = 'BOM'
    AND job_srnum = '62100113476'
    AND client_carton_no = 'BM4060394822'
    AND subject = 'FILES'
    ORDER BY file_no
    Execution Plan:
    Operation Object Name Rows Bytes Cost
    SELECT STATEMENT Optimizer Mode=CHOOSE 1 15
    SORT ORDER BY 1 155 15
    TABLE ACCESS BY INDEX ROWID ISTORET.RMST_INVENTORY_DETAILS2 1 155 5
    INDEX RANGE SCAN ISTORET.BRC_JOB_SUB_REF123_INDX 1 4
    Query time: More than 5 mins
    Same query with hint /*+ index(rmst_inventory_details2 BRC_JOB_CTN_FILE_INDX) */
    SELECT STATEMENT Optimizer Mode=CHOOSE 1 6
    TABLE ACCESS BY INDEX ROWID ISTORET.RMST_INVENTORY_DETAILS2 1 155 6
    INDEX RANGE SCAN ISTORET.BRC_JOB_CTN_FILE_INDX 1 5
    Query time: 110 msecs
    Index details:
    PARAMETER INDEX- 1 INDEX- 2
    Table Owner ISTORET ISTORET
    Table Name RMST_INVENTORY_DETAILS2 RMST_INVENTORY_DETAILS2
    Index Name BRC_JOB_CTN_FILE_INDX BRC_JOB_SUB_REF123_INDX
    Uniqueness NONUNIQUE NONUNIQUE
    Columns BRANCH_CODE
    JOB_SRNUM
    CLIENT_CARTON_NO
    FILE_NO BRANCH_CODE
    JOB_SRNUM
    SUBJECT
    REF1
    REF2
    REF3
    Table Type TABLE TABLE
    Status VALID VALID
    Tablespace ISTORET_RID2_INDX ISTORET_RID2_INDX
    Initial Extent Size 4,194,304 4,194,304
    Next Extent Size 4,194,304 4,194,304
    Minimum Extents 1 1
    Maximum Extents 2,147,483,645 2,147,483,645
    Percent Increase 0 0
    Distinct Keys 42,576,227 27,318,132
    Percent Free 10 10
    Index Type NORMAL NORMAL
    Partitioned No No
    Temporary No No
    Join Index No No
    Size in MB 2,456 2,140
    Number Extents 614 535
    Size in bytes 2,575,302,656 2,243,952,640
    Last Analyzed 20/3/2007 20/3/2007

  • Peformance tuning of query using bitmap indexes

    Hello guys
    I just have a quick question about tuning the performance of sql query using bitmap indexes..
    Currently, there are 2 tables, date and fact. Fact table has about 1 billion row and date dim has about 1 million. These 2 tables are joined by 2 columns:
    Date.Dateid = Fact.snapshot.dates and Date.companyid = fact.companynumber
    I have query that needs to be run as the following:
    Select dates.dayofweek, dates,dates, fact.opened_amount from dates, facts
    where Date.Dateid = Fact.snapshot.dates and Date.companyid = fact.companynumber and dates.dayofweek = 'monday'.
    Currently this query is running forever. I think it is joining that takes a lot of time. I have created bitmap index on dayofweek column because it's low on distinctive rows. But it didn't seem to speed up with the performance..
    I'd like to know what other indexes will be helpful for me.. I am thinking of creating another one for companynumber since it also have low distinctive records.
    Currently the query is being generated by frontend tools like OBIEE so I can't change the sql nor can't I purge data or create smaller table, I have to what with what I have..
    So please let me know your thoughts in terms of performance tunings.
    Thanks

    The explain plan is:
    Row cost Bytes
    Select statement optimizer 1 1
    nested loops 1 1 299
    partition list all 1 0 266
    index full scan RD_T.PK_FACTS_SNPSH 1 0 266
    TABLE ACCESS BY INDEX ROWID DATES_DIM 1 1 33
    INDEX UNIQUE SCAN DATES_DIM_DATE 1 1
    There is no changes nor wait states, but query is taking 18 mins to return results. When it does, it returns 1 billion rows, which is the same number of rows of the fact table....(strange?)That's not a bitmap plan. Plans using bitmaps should have steps indicating bitmap conversions; this plan is listing ordinary btree index access. The rows and bytes on the plan for the volume of data you suggested have to be incorrect. (1 row instead of 1B?????)
    What version of the data base are you using?
    What is your partition key?
    Are the partioned table indexes global or local? Is the partition key part of the join columns, and is it indexed?
    Analyze the tables and all indexes (use dbms_stats) and see if the statistics get better. If that doesn't work try the dynamic sampling hint (there is some overhead for this) to get statistics at runtime.
    I have seen stats like the ones you listed appear in 10g myself.
    Edited by: riedelme on Oct 30, 2009 10:37 AM

  • Query not using index when using 'or' clause

    I have a problem with something I can't understand about indexes in Oracle 11g.
    We can create test data with:
    create table test2(field1 varchar2(100),field2 varchar2(100),field3 number,field4 varchar2(100));
    create index test2_idx1 on test2(upper(field1));
    create index test2_idx1b on test2(field1);
    create index test2_idx2 on test2(field3);
    DECLARE
    j NUMBER :=1;
    BEGIN
    FOR i IN 1..500000
    LOOP
    INSERT
    INTO test2
    (field1,field2, field3, field4)
    VALUES
    ('field1='||i,'a', j, 'i' );
    IF (i mod 1000)=0 THEN
    j := j+1;
    END IF;
    END LOOP;
    COMMIT;
    END;
    EXEC DBMS_STATS.GATHER_TABLE_STATS ('system', 'test2');
    Then I make some explain plans which result I can't understand
    Query 1:
    SELECT * FROM test2 WHERE field3=1;
    Explain plan:
    Explain plan for query 01
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1003 | 28084 | 10 (0)| 00:00:01 |
    | 1 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1003 | 28084 | 10 (0)| 00:00:01 |
    |* 2 | INDEX RANGE SCAN | TEST2_IDX2 | 1003 | | 5 (0)| 00:00:01 |
    Everything OK here. Index is used.
    Query 2:
    SELECT * FROM test2 WHERE upper(field1)='FIELD1=1';
    Explain plan
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1 | 28 | 4 (0)| 00:00:01 |
    | 1 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1 | 28 | 4 (0)| 00:00:01 |
    |* 2 | INDEX RANGE SCAN | TEST2_IDX1 | 1 | | 3 (0)| 00:00:01 |
    Everything OK again. Index is used.
    Query 3:
    SELECT /*+ USE_CONCAT */ * FROM test2 WHERE field1='FIELD1=1' OR field3=1;
    Explain plan
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1004 | 28112 | 14 (0)| 00:00:01 |
    | 1 | CONCATENATION | | | | | |
    | 2 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1 | 28 | 4 (0)| 00:00:01 |
    |* 3 | INDEX RANGE SCAN | TEST2_IDX1B | 1 | | 3 (0)| 00:00:01 |
    |* 4 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1003 | 28084 | 10 (0)| 00:00:01 |
    |* 5 | INDEX RANGE SCAN | TEST2_IDX2 | 1003 | | 5 (0)| 00:00:01 |
    Indenxes are used in concatenation. No problem again.
    Query 4:
    SELECT /*+ USE_CONCAT */ * FROM test2 WHERE upper(field1)='FIELD1=1' OR field3=1;
    Explain plan
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1004 | 28112 | 641 (4)| 00:00:08 |
    | 1 | CONCATENATION | | | | | |
    |* 2 | TABLE ACCESS FULL | TEST2 | 1 | 28 | 631 (4)| 00:00:08 |
    |* 3 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1003 | 28084 | 10 (0)| 00:00:01 |
    |* 4 | INDEX RANGE SCAN | TEST2_IDX2 | 1003 | | 5 (0)| 00:00:01 |
    Here my problem arises. Why is test2_idx1 not being used? Is it because it is a function index? Is there any workaround in this cases?
    Thanks a lot in advance.

    Interesting. A "workaround" which I thought first was:
    SELECT /*+ USE_CONCAT */ * FROM test2 WHERE upper(field1)='FIELD1=1'
    UNION ALL
    SELECT /*+ USE_CONCAT */ * FROM test2 WHERE field3=1;
    | Id  | Operation                    | Name       | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                                 
    |   0 | SELECT STATEMENT             |            |  1001 | 28042 |    15  (74)| 00:00:01 |                                                                                                                                                                                                                 
    |   1 |  UNION-ALL                   |            |       |       |            |          |                                                                                                                                                                                                                 
    |   2 |   TABLE ACCESS BY INDEX ROWID| TEST2      |     1 |    42 |     4   (0)| 00:00:01 |                                                                                                                                                                                                                 
    |*  3 |    INDEX RANGE SCAN          | TEST2_IDX1 |     1 |       |     3   (0)| 00:00:01 |                                                                                                                                                                                                                 
    |   4 |   TABLE ACCESS BY INDEX ROWID| TEST2      |  1000 | 28000 |    11   (0)| 00:00:01 |                                                                                                                                                                                                                 
    |*  5 |    INDEX RANGE SCAN          | TEST2_IDX2 |  1000 |       |     5   (0)| 00:00:01 |                                                                                                                                                                                                                 
    -------------------------------------------------------------------------------------------   But I do not like using UNION for such tricks. So I thought, what would ORACLE do without hint?
    SELECT  * FROM test2 WHERE upper(field1)='FIELD1=1' or field3=1;
    | Id  | Operation                        | Name       | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                             
    |   0 | SELECT STATEMENT                 |            |  1001 | 42042 |   176   (0)| 00:00:03 |                                                                                                                                                                                                             
    |   1 |  TABLE ACCESS BY INDEX ROWID     | TEST2      |  1001 | 42042 |   176   (0)| 00:00:03 |                                                                                                                                                                                                             
    |   2 |   BITMAP CONVERSION TO ROWIDS    |            |       |       |            |          |                                                                                                                                                                                                             
    |   3 |    BITMAP OR                     |            |       |       |            |          |                                                                                                                                                                                                             
    |   4 |     BITMAP CONVERSION FROM ROWIDS|            |       |       |            |          |                                                                                                                                                                                                             
    |*  5 |      INDEX RANGE SCAN            | TEST2_IDX2 |       |       |     5   (0)| 00:00:01 |                                                                                                                                                                                                             
    |   6 |     BITMAP CONVERSION FROM ROWIDS|            |       |       |            |          |                                                                                                                                                                                                             
    |*  7 |      INDEX RANGE SCAN            | TEST2_IDX1 |       |       |     3   (0)| 00:00:01 |                                                                                                                                                                                                             
    ----------------------------------------------------------------------------------------------- Thist looks perfect to me. (Please ignore the "higher" cost on the second plan. On your real data, it should be faster. Is it?)

  • Why does not my query use an index?

    I have a table with some processed rows (state: 9) and some unprocessed rows (states: 0,1,2,3,4).
    This table has over 120000 rows, but this number will grow.
    Most of the rows are processed and most of them also contain a group id. Number of groups is relatively small (let's assume 20).
    I would like to obtain the oldest some_date for every group. This values has to be outer joined to a on-line report (contains one row for each group).
    Here is my set-up:
    Tested on: 10.2.0.4 (Solaris), 10.2.0.1 (WinXp)
    drop table t purge;
    create table t(
      id number not null primary key,
      grp_id number,
      state number,
      some_date date,
      pad char(200)
    insert into t(id, grp_id, state, some_date, pad)
    select level,
         trunc(dbms_random.value(0,20)),
            9,
            sysdate+dbms_random.value(1,100),
            'x'
    from dual
    connect by level <= 120000;
    insert into t(id, grp_id, state, some_date, pad)
    select level + 120000,
         trunc(dbms_random.value(0,20)),
            trunc(dbms_random.value(0,5)),
            sysdate+dbms_random.value(1,100),
            'x'
    from dual
    connect by level <= 2000;
    commit;
    exec dbms_stats.gather_table_stats(user, 'T', estimate_percent=>100, method_opt=>'FOR ALL COLUMNS SIZE 1');
    Tom Kyte's printtab
    ==============================
    TABLE_NAME                    : T
    NUM_ROWS                      : 122000
    BLOCKS                        : 3834I know, this could be easily solved by fast refresh on commit materialized view like this:
    select
      grp_id,
      min(some_date),
    from
      t
    where
      state in (0,1,2,3,4)
    grpup by
      grp_id;+ I have to create log on (grp_id, some_date, state)
    Number of rows with active state will be always relatively small. Let's assume 1000-2000.
    So my another idea was to create a selective index. An index which would contain only data for rows with an active state.
    Something like this:
    create index fidx_active on t ( 
      case state 
        when 0 then grp_id
        when 1 then grp_id
        when 2 then grp_id
        when 3 then grp_id
        when 4 then grp_id
      end,
      case state
        when 0 then some_date
        when 1 then some_date
        when 2 then some_date
        when 3 then some_date
        when 4 then some_date
      end) compress 1; so a tuple (group_id, some_date) is projected to tuple (null, null) when the state is not an active state and therefore it is not indexed.
    We can save even more space by compressing 1st expression.
    analyze index idx_grp_state_date validate structure;
    select * from index_stats
    @pr
    Tom Kyte's printtab
    ==============================
    HEIGHT                        : 2
    BLOCKS                        : 16
    NAME                          : FIDX_ACTIV
    LF_ROWS                       : 2000 <-- we're indexing only active rows
    LF_BLKS                       : 6 <-- small index: 1 root block with 6 leaf blocks
    BR_ROWS                       : 5
    BR_BLKS                       : 1
    DISTINCT_KEYS                 : 2000
    PCT_USED                      : 69
    PRE_ROWS                      : 25
    PRE_ROWS_LEN                  : 224
    OPT_CMPR_COUNT                : 1
    OPT_CMPR_PCTSAVE              : 0Note: @pr is a Tom Kyte's print table script adopted by Tanel Poder (I'm using Tanel's library) .
    Then I created a query to be outer joined to the report (report contains a row for every group).
    I want to achieve a full scan of the index.
    select
      case state -- 1st expression
        when 0 then grp_id
        when 1 then grp_id
        when 2 then grp_id
        when 3 then grp_id
        when 4 then grp_id
      end grp_id,
      min(case state --second expression
            when 0 then some_date
            when 1 then some_date
            when 2 then some_date
            when 3 then some_date
            when 4 then some_date
          end) as mintime
    from t 
    where
      case state --1st expression: at least one index column has to be not null
        when 0 then grp_id
        when 1 then grp_id
        when 2 then grp_id
        when 3 then grp_id
        when 4 then grp_id
      end is not null
    group by
      case state --1st expression
        when 0 then grp_id
        when 1 then grp_id
        when 2 then grp_id
        when 3 then grp_id
        when 4 then grp_id
      end;-------------
    Doc's snippet:
    13.5.3.6 Full Scans
    A full scan is available if a predicate references one of the columns in the index. The predicate does not need to be an index driver. A full scan is also available when there is no predicate, if both the following conditions are met:
    All of the columns in the table referenced in the query are included in the index.
    At least one of the index columns is not null.
    A full scan can be used to eliminate a sort operation, because the data is ordered by the index key. It reads the blocks singly.
    13.5.3.7 Fast Full Index Scans
    Fast full index scans are an alternative to a full table scan when the index contains all the columns that are needed for the query, and at least one column in the index key has the NOT NULL constraint. A fast full scan accesses the data in the index itself, without accessing the table. It cannot be used to eliminate a sort operation, because the data is not ordered by the index key. It reads the entire index using multiblock reads, unlike a full index scan, and can be parallelized.
    You can specify fast full index scans with the initialization parameter OPTIMIZER_FEATURES_ENABLE or the INDEX_FFS hint. Fast full index scans cannot be performed against bitmap indexes.
    A fast full scan is faster than a normal full index scan in that it can use multiblock I/O and can be parallelized just like a table scan.
    So the question is: Why does oracle do a full table scan?
    Everything needed is in the index and one expression is not null, but index (fast) full scan is not even considered by CBO (I did a 10053 trace)
    | Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   1 |  HASH GROUP BY     |      |      1 |     85 |     20 |00:00:00.11 |    3841 |
    |*  2 |   TABLE ACCESS FULL| T    |      1 |   6100 |   2000 |00:00:00.10 |    3841 |
    Predicate Information (identified by operation id):
       2 - filter(CASE "STATE" WHEN 0 THEN "GRP_ID" WHEN 1 THEN "GRP_ID" WHEN 2
                  THEN "GRP_ID" WHEN 3 THEN "GRP_ID" WHEN 4 THEN "GRP_ID" END  IS NOT NULL)Let's try some minimalistic examples. Firstly with no FBI.
    create index idx_grp_id on t(grp_id);
    select grp_id,
           min(grp_id) min
    from t
    where grp_id is not null
    group by grp_id;
    | Id  | Operation             | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
    |   1 |  HASH GROUP BY        |            |      1 |     20 |     20 |00:00:01.00 |     244 |    237 |
    |*  2 |   INDEX FAST FULL SCAN| IDX_GRP_ID |      1 |    122K|    122K|00:00:00.54 |     244 |    237 |
    Predicate Information (identified by operation id):
       2 - filter("GRP_ID" IS NOT NULL)This kind of output I was expected to see with FBI. Index FFS was used although grp_id has no NOT NULL constraint.
    Let's try a simple FBI.
    create index fidx_grp_id on t(trunc(grp_id));
    select trunc(grp_id),
           min(trunc(grp_id)) min
    from t
    where trunc(grp_id) is not null
    group by trunc(grp_id);
    | Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   1 |  HASH GROUP BY     |      |      1 |     20 |     20 |00:00:00.94 |    3841 |
    |*  2 |   TABLE ACCESS FULL| T    |      1 |   6100 |    122K|00:00:00.49 |    3841 |
    Predicate Information (identified by operation id):
       2 - filter(TRUNC("GRP_ID") IS NOT NULL)Again, index (fast) full scan not even considered by CBO.
    I tried:
    alter table t modify grp_id not null;
    alter table t add constraint trunc_not_null check (trunc(grp_id) is not null);I even tried to set table hidden column (SYS_NC00008$) to NOT NULL
    It has no effect, FTS is still used..
    Let's try another query:
    select distinct trunc(grp_id)
    from t
    where trunc(grp_id) is not null
    | Id  | Operation             | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   1 |  HASH UNIQUE          |             |      1 |     20 |     20 |00:00:00.85 |     244 |
    |*  2 |   INDEX FAST FULL SCAN| FIDX_GRP_ID |      1 |    122K|    122K|00:00:00.49 |     244 |
    Predicate Information (identified by operation id):
       2 - filter("T"."SYS_NC00008$" IS NOT NULL)Here the index FFS is used..
    Let's try one more query, very similar to the above query:
    select trunc(grp_id)
    from t
    where trunc(grp_id) is not null
    group by trunc(grp_id)
    | Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   1 |  HASH GROUP BY     |      |      1 |     20 |     20 |00:00:00.86 |    3841 |
    |*  2 |   TABLE ACCESS FULL| T    |      1 |    122K|    122K|00:00:00.49 |    3841 |
    Predicate Information (identified by operation id):
       2 - filter(TRUNC("GRP_ID") IS NOT NULL)And again no index full scan..
    So my next question is:
    What are the restrictions which prevent index (fast) fullscan to be used in these scenarios?
    Thank you very much for your answers.
    Edited by: user1175494 on 16.11.2010 15:23
    Edited by: user1175494 on 16.11.2010 15:25

    I'll start off with the caveat that i'm no Johnathan Lewis so hopefully someone will be able to come along and give you a more coherent explanation than i'm going to attempt here.
    It looks like the application of the MIN function against the case statement is confusing the optimizer and disallowing the usage of your FBI. I tested this against my 11.2.0.1 instance and your query chooses the fast full scan without being nudged in the right direction.
    That being said, i was able to get this to use a fast full scan on my 10 instance, but i had to jiggle the wires a bit. I modified your original query slightly, just to make it easier to do my fiddling.
    original (in the sense that it still takes the full table scan) query
    with data as
      select
        case state -- 1st expression
          when 0 then grp_id
          when 1 then grp_id
          when 2 then grp_id
          when 3 then grp_id
          when 4 then grp_id
        end as grp_id,
        case state --second expression
              when 0 then some_date
              when 1 then some_date
              when 2 then some_date
              when 3 then some_date
              when 4 then some_date
        end as mintime
      from t
      where
        case state --1st expression: at least one index column has to be not null
          when 0 then grp_id
          when 1 then grp_id
          when 2 then grp_id
          when 3 then grp_id
          when 4 then grp_id
        end is not null
      and
        case state --second expression
              when 0 then some_date
              when 1 then some_date
              when 2 then some_date
              when 3 then some_date
              when 4 then some_date
        end is not null 
    select--+ GATHER_PLAN_STATISTICS
      grp_id,
      min(mintime)
    from data
    group by grp_id;
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'allstats  +peeked_binds'));
    | Id  | Operation        | Name | Starts | E-Rows | A-Rows |      A-Time   | Buffers |
    |   1 |  HASH GROUP BY        |       |      2 |      33 |       40 |00:00:00.07 |    7646 |
    |*  2 |   TABLE ACCESS FULL| T       |      2 |      33 |     4000 |00:00:00.08 |    7646 |
    Predicate Information (identified by operation id):
       2 - filter((CASE "STATE" WHEN 0 THEN "GRP_ID" WHEN 1 THEN "GRP_ID" WHEN 2
               THEN "GRP_ID" WHEN 3 THEN "GRP_ID" WHEN 4 THEN "GRP_ID" END  IS NOT NULL AND
               CASE "STATE" WHEN 0 THEN "SOME_DATE" WHEN 1 THEN "SOME_DATE" WHEN 2 THEN
               "SOME_DATE" WHEN 3 THEN "SOME_DATE" WHEN 4 THEN "SOME_DATE" END  IS NOT
               NULL))
    modified version where we prevent the MIN function from being applied too early, by using ROWNUM
    with data as
      select
        case state -- 1st expression
          when 0 then grp_id
          when 1 then grp_id
          when 2 then grp_id
          when 3 then grp_id
          when 4 then grp_id
        end as grp_id,
        case state --second expression
              when 0 then some_date
              when 1 then some_date
              when 2 then some_date
              when 3 then some_date
              when 4 then some_date
        end as mintime
      from t
      where
        case state --1st expression: at least one index column has to be not null
          when 0 then grp_id
          when 1 then grp_id
          when 2 then grp_id
          when 3 then grp_id
          when 4 then grp_id
        end is not null
      and
        case state --second expression
              when 0 then some_date
              when 1 then some_date
              when 2 then some_date
              when 3 then some_date
              when 4 then some_date
        end is not null 
      and rownum > 0
    select--+ GATHER_PLAN_STATISTICS
      grp_id,
      min(mintime)
    from data
    group by grp_id;
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'allstats  +peeked_binds'));
    | Id  | Operation           | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   1 |  HASH GROUP BY           |            |      2 |     20 |     40 |00:00:00.01 |      18 |
    |   2 |   VIEW                |            |      2 |     33 |   4000 |00:00:00.07 |      18 |
    |   3 |    COUNT           |            |      2 |      |   4000 |00:00:00.05 |      18 |
    |*  4 |     FILTER           |            |      2 |      |   4000 |00:00:00.03 |      18 |
    |*  5 |      INDEX FAST FULL SCAN| FIDX_ACTIVE |      2 |     33 |   4000 |00:00:00.01 |      18 |
    Predicate Information (identified by operation id):
       4 - filter(ROWNUM>0)
       5 - filter(("T"."SYS_NC00006$" IS NOT NULL AND "T"."SYS_NC00007$" IS NOT NULL))

  • Select query with secondary index

    hi,
    i have a report which is giving performance issues on a perticular select query on KONH table.
    the select query doesnt use the primary key fields and table already has around 19 million entries.So there was a secondary index created for the fields in the table.
    now, KONH is a client specific table, and hence has MANDT as the first field. when the table is not indexed it is sorted according to the order of fields, like first MANDT, then primary key fields and then remaining fields.. (correct me if i am wrong)
    but the secondary index created doesnt has MANDT in it..(yea, a mistake! )...
    but instead of correccting the secondary index, i am told to change the select query..
    so, i used a "client specific" syntax to sort the issue.. but i dont understand whre i should put the "where mandt eq sy-mandt" clause..
    should i put it right after all my secondary index fields are over? or what happens to the order of fields which are not present in the list of secondary index?
    kindaly help.
    thanx.

    Hi chinmay kulkarni,
    its better if you can ask concerned person to add MANDT field in your  index as well....
    Indexes and MANDT
    If a table begins with the mandt field, so should its indexes. If a table begins with mandt and an index doesn't, the optimizer might not use the index.
    Remember, if you will, Open SQL's automatic client handling feature. When select * from ztxlfa1 where land1 = 'US' is executed, the actual SQL sent to the database is select * from ztxlfa1 where mandt = sy-mandt and land1 = 'US'. Sy-mandt contains the current logon client. When you select rows from a table using Open SQL, the system automatically adds sy-mandt to the where clause, which causes only those rows pertaining to the current logon client to be found.
    When you create an index on a table containing mandt, therefore, you should also include mandt in the index. It should come first in the index, because it will always appear first in the generated SQL.
    Index: Technical key of a database table.
    Primary index: The primary index contains the key fields of the table and a pointer to the non-key fields of the table. The primary index is created automatically when the table is created in the database.
    Secondary index: Additional indexes could be created considering the most frequently accessed dimensions of the table.
    Structure of an Index
    An index can be used to speed up the selection of data records from a table.
    An index can be considered to be a copy of a database table reduced to certain fields. The data is stored in sorted form in this copy. This sorting permits fast access to the records of the table (for example using a binary search). Not all of the fields of the table are contained in the index. The index also contains a pointer from the index entry to the corresponding table entry to permit all the field contents to be read.
    When creating indexes, please note that:
    An index can only be used up to the last specified field in the selection! The fields which are specified in the WHERE clause for a large number of selections should be in the first position.
    Only those fields whose values significantly restrict the amount of data are meaningful in an index.
    When you change a data record of a table, you must adjust the index sorting. Tables whose contents are frequently changed therefore should not have too many indexes.
    Make sure that the indexes on a table are as disjunctive as possible.
    (That is they should contain as few fields in common as possible. If two indexes on a table have a large number of common fields, this could make it more difficult for the optimizer to choose the most selective index.)
    For Example...
    SELECT KUNNR KUNN2 INTO TABLE T_CUST_TERR
    FROM KNVP CLIENT SPECIFIED
    WHERE MANDT = SY-MANDT " here MANDT shd be first
    AND KUNN2 IN S_TERR
    AND PARVW LIKE 'Z%'.
    Accessing tables using Indexes
    The database optimizer decides which index on the table should be used by the database to access data records.
    You must distinguish between the primary index and secondary indexes of a table. The primary index contains the key fields of the table. The primary index is automatically created in the database when the table is activated. If a large table is frequently accessed such that it is not possible to apply primary index sorting, you should create secondary indexes for the table.
    The indexes on a table have a three-character index ID. '0' is reserved for the primary index. Customers can create their own indexes on SAP tables; their IDs must begin with Y or Z.
    If the index fields have key function, i.e. they already uniquely identify each record of the table, an index can be called a unique index. This ensures that there are no duplicate index fields in the database.
    When you define a secondary index in the ABAP Dictionary, you can specify whether it should be created on the database when it is activated. Some indexes only result in a gain in performance for certain database systems. You can therefore specify a list of database systems when you define an index. The index is then only created on the specified database systems when activated
    Also pls have a look on below link
    http://www.sapfans.com/sapfans/forum/devel/messages/30240.html
    Hope it will solve your problem..
    Reward points if useful...
    Thanks & Regards
    ilesh 24x7

  • How to know whether query is using Indexes in oracle?

    Please let me know necessary steps to check whether query using indexes.

    Try the below and check the explain plan.. See below explain plan using index marked as "RED" font
    SET AUTOTRACE TRACEONLY EXPLAIN
    SELECT * FROM emp WHERE empno = 7839;
    Execution Plan
    Plan hash value: 2949544139
    | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT            |        |     1 |    38 |     1   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:00:01 |
    |*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       2 - access("EMPNO"=7839)

  • Query not using indexes

    select *
              from hrm_career x
              WHERE x.begin_date = ( SELECT MAX(begin_date)
                             FROM hrm_career y
                             WHERE y.employee_id = x.employee_id AND
                                  begin_date <= SYSDATE AND
                                  primary_job = 'Y') AND
                   x.primary_job = 'Y'
    I have the above query which is not using the index created on the BEGIN_DT column
    I tried to force using still not using
    but when i apply a value say
    select *
              from hrm_career x
              WHERE x.begin_date ='10-20-2007'
    It is using index and resulting in very fast response
    Can some throw some ideas on it...
    Where should i look into here ..

    SQL> set autotrace traceonly
    SQL> select *
    2 from hrm_career x
    3 WHERE x.begin_date = ( SELECT MAX(begin_date)
    4 FROM hrm_career y
    5 WHERE y.employee_id = x.employee_id AND
    6 begin_date <= SYSDATE AND
    7 primary_job = 'Y') AND
    8 x.primary_job = 'Y';
    13454 rows selected.
    Execution Plan
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1417 Card=152 Bytes=
    35568)
    1 0 FILTER
    2 1 SORT (GROUP BY) (Cost=1417 Card=152 Bytes=35568)
    3 2 HASH JOIN (Cost=254 Card=47127 Bytes=11027718)
    4 3 INDEX (FAST FULL SCAN) OF 'HRM_CAREER_PK' (UNIQUE) (
    Cost=12 Card=25026 Bytes=500520)
    5 3 TABLE ACCESS (FULL) OF 'HRM_CAREER' (Cost=81 Card=25
    335 Bytes=5421690)
    Statistics
    3671 recursive calls
    9 db block gets
    1758 consistent gets
    2130 physical reads
    0 redo size
    2217762 bytes sent via SQL*Net to client
    10359 bytes received via SQL*Net from client
    898 SQL*Net roundtrips to/from client
    128 sorts (memory)
    1 sorts (disk)
    13454 rows processed
    TKPROF
    TKPROF: Release 9.2.0.6.0 - Production on Wed Dec 12 18:40:56 2007
    Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
    Trace file: qnhg_ora_500.trc
    Sort options: default
    count = number of times OCI procedure was executed
    cpu = cpu time in seconds executing
    elapsed = elapsed time in seconds executing
    disk = number of physical reads of buffers from disk
    query = number of buffers gotten for consistent read
    current = number of buffers gotten in current mode (usually for update)
    rows = number of rows processed by the fetch or execute call
    ALTER SESSION SET EVENTS '10046 trace name context forever, level 8'
    call count cpu elapsed disk query current rows
    Parse 0 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 0 0.00 0.00 0 0 0 0
    total 1 0.00 0.00 0 0 0 0
    Misses in library cache during parse: 0
    Misses in library cache during execute: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 1 0.00 0.00
    SQL*Net message from client 1 34.45 34.45
    select condition
    from
    cdef$ where rowid=:1
    call count cpu elapsed disk query current rows
    Parse 4 0.00 0.00 0 0 0 0
    Execute 4 0.00 0.00 0 0 0 0
    Fetch 4 0.00 0.00 0 8 0 4
    total 12 0.00 0.00 0 8 0 4
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: SYS (recursive depth: 1)
    Rows Row Source Operation
    1 TABLE ACCESS BY USER ROWID CDEF$
    select *
    from hrm_career x
    WHERE x.begin_date = ( SELECT MAX(begin_date)
    FROM hrm_career y
    WHERE y.employee_id = x.employee_id AND
    begin_date <= SYSDATE AND
    primary_job = 'Y') AND
    x.primary_job = 'Y'
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.07 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 898 0.00 2.39 2038 946 9 13454
    total 900 0.00 2.46 2038 946 9 13454
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Rows Row Source Operation
    13454 FILTER
    25335 SORT GROUP BY
    67496 HASH JOIN
    25333 INDEX FAST FULL SCAN HRM_CAREER_PK (object id 25292)
    25336 TABLE ACCESS FULL HRM_CAREER
    Rows Execution Plan
    0 SELECT STATEMENT GOAL: CHOOSE
    13454 FILTER
    25335 SORT (GROUP BY)
    67496 HASH JOIN
    25333 INDEX GOAL: ANALYZED (FAST FULL SCAN) OF 'HRM_CAREER_PK'
    (UNIQUE)
    25336 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'HRM_CAREER'
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 898 0.00 0.00
    SQL*Net more data to client 877 0.00 0.05
    db file sequential read 1 0.01 0.01
    db file scattered read 60 0.00 0.14
    direct path write 9 0.00 0.00
    direct path read 125 0.05 0.13
    SQL*Net message from client 898 0.02 1.47
    DELETE FROM PLAN_TABLE
    WHERE
    STATEMENT_ID=:1
    call count cpu elapsed disk query current rows
    Parse 2 0.00 0.00 0 0 0 0
    Execute 2 0.00 0.00 0 6 6 6
    Fetch 0 0.00 0.00 0 0 0 0
    total 4 0.00 0.00 0 6 6 6
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Rows Row Source Operation
    0 DELETE
    0 TABLE ACCESS FULL PLAN_TABLE
    Rows Execution Plan
    0 DELETE STATEMENT GOAL: CHOOSE
    0 DELETE OF 'PLAN_TABLE'
    0 TABLE ACCESS (FULL) OF 'PLAN_TABLE'
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 2 0.00 0.00
    SQL*Net message from client 2 14.77 14.79
    select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname,
    o.dataobj#,o.flags
    from
    obj$ o where o.obj#=:1
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.00 0.00 0 3 0 1
    total 3 0.00 0.00 0 3 0 1
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: SYS (recursive depth: 1)
    EXPLAIN PLAN SET STATEMENT_ID='PLUS74964' FOR select *
    from hrm_career x
    WHERE x.begin_date = ( SELECT MAX(begin_date)
    FROM hrm_career y
    WHERE y.employee_id = x.employee_id AND
    begin_date <= SYSDATE AND
    primary_job = 'Y') AND
    x.primary_job = 'Y'
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.01 0 4 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 0 0.00 0.00 0 0 0 0
    total 2 0.00 0.01 0 4 0 0
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 1 0.00 0.00
    SQL*Net message from client 1 0.00 0.00
    insert into plan_table (statement_id, timestamp, operation, options,
    object_node, object_owner, object_name, object_instance, object_type,
    search_columns, id, parent_id, position, other,optimizer, cost, cardinality,
    bytes, other_tag, partition_start, partition_stop, partition_id,
    distribution, cpu_cost, io_cost, temp_space, access_predicates,
    filter_predicates )
    values
    (:1,SYSDATE,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,
    :20,:21,:22,:23,:24,:25,:26,:27)
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 6 0.00 0.00 0 3 6 6
    Fetch 0 0.00 0.00 0 0 0 0
    total 7 0.00 0.00 0 3 6 6
    Misses in library cache during parse: 1
    Misses in library cache during execute: 2
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN) (recursive depth: 1)
    Rows Execution Plan
    0 INSERT STATEMENT GOAL: CHOOSE
    select o.name, u.name
    from
    sys.obj$ o, sys.user$ u where obj# = :1 and owner# = user#
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 0 0.00 0.00 0 0 0 0
    Fetch 0 0.00 0.00 0 0 0 0
    total 1 0.00 0.00 0 0 0 0
    Misses in library cache during parse: 1
    Parsing user id: SYS (recursive depth: 1)
    SELECT ID ID_PLUS_EXP,PARENT_ID PARENT_ID_PLUS_EXP,LPAD(' ',2*(LEVEL-1))
    ||OPERATION||DECODE(OTHER_TAG,NULL,'','*')||DECODE(OPTIONS,NULL,'','
    ('||OPTIONS||')')||DECODE(OBJECT_NAME,NULL,'',' OF '''||OBJECT_NAME||'''')
    ||DECODE(OBJECT_TYPE,NULL,'',' ('||OBJECT_TYPE||')')||DECODE(ID,0,
    DECODE(OPTIMIZER,NULL,'',' Optimizer='||OPTIMIZER))||DECODE(COST,NULL,'','
    (Cost='||COST||DECODE(CARDINALITY,NULL,'',' Card='||CARDINALITY)
    ||DECODE(BYTES,NULL,'',' Bytes='||BYTES)||')') PLAN_PLUS_EXP,OBJECT_NODE
    OBJECT_NODE_PLUS_EXP
    FROM
    PLAN_TABLE START WITH ID=0 AND STATEMENT_ID=:1 CONNECT BY PRIOR ID=PARENT_ID
    AND STATEMENT_ID=:1 ORDER BY ID,POSITION
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 2 0.00 0.00 0 22 0 6
    total 4 0.00 0.00 0 22 0 6
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Rows Row Source Operation
    6 SORT ORDER BY
    6 CONNECT BY WITH FILTERING
    1 NESTED LOOPS
    1 TABLE ACCESS FULL PLAN_TABLE
    1 TABLE ACCESS BY USER ROWID PLAN_TABLE
    5 NESTED LOOPS
    6 BUFFER SORT
    6 CONNECT BY PUMP
    5 TABLE ACCESS FULL PLAN_TABLE
    Rows Execution Plan
    0 SELECT STATEMENT GOAL: CHOOSE
    6 SORT (ORDER BY)
    6 CONNECT BY (WITH FILTERING)
    1 NESTED LOOPS
    1 TABLE ACCESS (FULL) OF 'PLAN_TABLE'
    1 TABLE ACCESS (BY USER ROWID) OF 'PLAN_TABLE'
    5 NESTED LOOPS
    6 BUFFER (SORT)
    6 CONNECT BY PUMP
    5 TABLE ACCESS (FULL) OF 'PLAN_TABLE'
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 2 0.00 0.00
    SQL*Net message from client 2 0.09 0.09
    SELECT ID ID_PLUS_EXP,OTHER_TAG OTHER_TAG_PLUS_EXP,OTHER OTHER_PLUS_EXP
    FROM
    PLAN_TABLE WHERE STATEMENT_ID=:1 AND OTHER_TAG IS NOT NULL ORDER BY ID
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.00 0.00 0 3 0 0
    total 3 0.00 0.00 0 3 0 0
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    Rows Row Source Operation
    0 SORT ORDER BY
    0 TABLE ACCESS FULL PLAN_TABLE
    Rows Execution Plan
    0 SELECT STATEMENT GOAL: CHOOSE
    0 SORT (ORDER BY)
    0 TABLE ACCESS (FULL) OF 'PLAN_TABLE'
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 2 0.00 0.00
    SQL*Net message from client 2 0.00 0.00
    ALTER SESSION SET EVENTS '10046 trace name context off'
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 0 0.00 0.00 0 0 0 0
    total 2 0.00 0.00 0 0 0 0
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 30 (ADMIN)
    OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
    call count cpu elapsed disk query current rows
    Parse 7 0.00 0.09 0 4 0 0
    Execute 8 0.00 0.00 0 6 6 6
    Fetch 901 0.00 2.39 2038 971 9 13460
    total 916 0.00 2.49 2038 981 15 13466
    Misses in library cache during parse: 6
    Misses in library cache during execute: 1
    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    SQL*Net message to client 906 0.00 0.00
    SQL*Net message from client 906 34.45 50.82
    SQL*Net more data to client 877 0.00 0.05
    db file sequential read 1 0.01 0.01
    db file scattered read 60 0.00 0.14
    direct path write 9 0.00 0.00
    direct path read 125 0.05 0.13
    OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
    call count cpu elapsed disk query current rows
    Parse 7 0.00 0.00 0 0 0 0
    Execute 11 0.00 0.00 0 3 6 6
    Fetch 5 0.00 0.00 0 11 0 5
    total 23 0.00 0.00 0 14 6 11
    Misses in library cache during parse: 4
    Misses in library cache during execute: 2
    9 user SQL statements in session.
    6 internal SQL statements in session.
    15 SQL statements in session.
    5 statements EXPLAINed in this session.
    Trace file: qnhg_ora_500.trc
    Trace file compatibility: 9.02.00
    Sort options: default
    3 sessions in tracefile.
    12 user SQL statements in trace file.
    8 internal SQL statements in trace file.
    15 SQL statements in trace file.
    11 unique SQL statements in trace file.
    5 SQL statements EXPLAINed using schema:
    ADMIN.prof$plan_table
    Default table was used.
    Table was created.
    Table was dropped.
    3945 lines in trace file.
    Message was edited by:
    Maran Viswarayar

  • Why does not  a query go by index but FULL TABLE SCAN

    I have two tables;
    table 1 has 1400 rwos and more than 30 columns , one of them is named as 'site_code' , a index was created on this column;
    table 2 has more 150 rows than 20 column , this primary key is 'site_code' also.
    the two tables were analysed by dbms_stats.gather_table()...
    when I run the explain for the 2 sqls below:
    select * from table1 where site_code='XXXXXXXXXX';
    select * from table1 where site_code='XXXXXXXXXX';
    certainly the oracle explain report show that 'Index scan'
    but the problem raised that
    I try to explain the sql
    select *
    from table1,table2
    where 1.'site_code'=2.'site_code'
    the explain report that :
    select .....
    FULL Table1 Scan
    FULL Table2 Scan
    why......

    Nikolay Ivankin  wrote:
    BluShadow wrote:
    Nikolay Ivankin  wrote:
    Try to use hint, but I really doubt it will be faster.No, using hints should only be advised when investigating an issue, not recommended for production code, as it assumes that, as a developer, you know better than the Oracle Optimizer how the data is distributed in the data files, and how the data is going to grow and change over time, and how best to access that data for performance etc.Yes, you are absolutly right. But aren't we performing such an investigation, are we? ;-)The way you wrote it, made it sound that a hint would be the solution, not just something for investigation.
    select * from .. always performs full scan, so limit your query.No, select * will not always perform a full scan, that's just selecting all the columns.
    A select without a where clause or that has a where clause that has low selectivity will result in full table scans.But this is what I have ment.But not what you said.

  • Issue with select query for secondary index

    Hi all,
    I have created a secondary index A on mara table with fields Mandt and Packaging Material Type VHART.
    Now i am trying to write a report
    Tables : mara.
    data : begin of itab occurs 0.
    include structure mara.
    data  : end of itab.
    *select * from mara into table itab*
    CLIENT SPECIFIED where
      MANDT = SY-MANDT and
      VHART = 'WER'.
    I'm getting an error
    Unable to interpret "CLIENT". Possible causes of error: Incorrect spelling or comma error.          
    if i change to my select query     to
    *select * from mara into table itab*
      where
      MANDT = SY-MANDT and
      VHART = 'WER'.
    I'm getting an error
    Without the addition "CLIENT SPECIFIED", you cannot specify the client     field "MANDT" in the WHERE condition.
    Let me know if iam wrong and we are at 4.6c
    Thanks

    Like I already said, even if you have added the mandt field in the secondary index, there is no need the use it in the select statement.
    Let me elaborate on my reply before. If you have created a UNIQUE index, which I don't think you have, then you should include CLIENT in the index. A unique index for a client-dependent table must contain the client field.
    Additional info:
    The accessing speed does not depend on whether or not an index is defined as a unique index. A unique index is simply a means of defining that certain field combinations of data records in a table are unique.
    Even if you have defined a secondary index, this does not automatically mean, that this index is used. This also depends on the database optimizer. The optimizer will determine which index is best and use it. So before transporting this index, you should make sure that the index is used. How to check this, have a look at the link:
    [check if index is used|http://help.sap.com/saphelp_nw70/helpdata/EN/cf/21eb3a446011d189700000e8322d00/content.htm]
    Edited by: Micky Oestreich on May 13, 2008 10:09 PM

  • Execution time of query on different indexes

    Hello,
    I have a query on the table, the execution time has hugh difference using different indexes on the table. The table has about 200,000 rows. Any explaination on it?
    Thanks,
    create table TB_test
    ( A1 number(9),
    A2 number(9)
    select count(*) from TB_test
    where A1=123 and A2=456;
    A. With index IDX_test on column A1:
    Create index IDX_test on TB_test(A1);
    Explain plan:
    SELECT STATEMENT
    Cost: 3,100
    SORT AGGREGATE
    Bytes: 38 Cardinality: 1
    TABLE ACCESS BY INDEX ROWID TABLE TB_test
    Cost: 3,100 Bytes: 36 Cardinality: 1
    INDEX RANGE SCAN INDEX IDX_test
    Cost: 40 Cardinality: 21,271
    Execution time is : 5 Minutes
    B. With index IDX_test on column A1 and A2:
    Create index IDX_test on TB_test(A1, A2);
    Explain plan:
    SELECT STATMENT
    Cost: 3 Bytes: 37 Cardinality: 1
    SORT AGGREGATE
    Bytes: 37 Cardinality: 1
    INDEX RANGE SCAN INDEZ IDX_test
    Cost: 3 Bytes 37 Cardinality:1
    Execution time is: 1.5 Seconds

    Additional you should check how many values you have in your table for the specific column values.
    The following select might be helful for that.
    select count(*)  "total_count"
           ,count(case when A1=123 then 1 end) "A1_count"
           ,count(case when A1=123 and A2=456 then 1 end) "A1andA2_count"
    from TB_test;Share your output of this.
    I expect the value for A1_count still to be high. But the value for A1+A2_count relatively low.
    However 5 minutes is far to long for such a small table. Even if you run it on a laptop.
    There must be a reason why it is that slow.
    First thing to consider would be to update your statistics for the table and the index.
    Second thing could be that the table is very sparsly fillled. Meaning, if you frequently delete records from this table and load new data using APPEND hint, then the table will grow, because the free space from the deletes is never reused. Any table access in the execution plan, will be slower then needed.
    A similar thing can happen, if many updates on previously empty columns are made on a table (row chaining problem).
    So if you explain a little, how this table is filled and used, we could recognize a typical pattern that leads to performance issues.
    Edited by: Sven W. on Nov 28, 2012 5:54 PM

  • Query not using index after delete?

    In 10 million table, i have purge a 5 millions and done table re-org, rebuilt of index and gather stats 100% including indexes.
    Query which is doing index scans eariler, now after purge explain plan has changed and its performing full table scan. Any idea, why behaviour has changed?
    its vendor based code can't change the query, any way to get back to index scan?

    Paulie wrote:
    Jonathan Lewis wrote:
    >
    I'm sure that Jonathan Lewis would not phrase it exactly like that, but in a nutshell, that's probably your answer.
    I certainly wouldn't phrase it like thatOf course not - I was merely poking fun at my rather simplistic and colloquial explanation - I certainly meant no
    offence.
    None taken (although perhaps I didn't make that clear enough -- I took your comment as tongue in cheek, anyway)
    >
    - and there definitely ISN'T a rule of thumb regarding proportion of data - Is it a common myth? I'm pretty sure that I have read about this "rule of thumb" to which I referred? I'll certainly
    take that on board in future.
    It is a very common myth - and one which various people have tried to dispel for years; unfortunately it gets resurrected fairly regularly by people who don't know any better. Critically, the choice of index is dictated by a combination of two factors, and mentioning one without the other is very misleading - the quantity of the data acquired and the scattering of the data. On top of that you have to remember that there are two "models" to consider - Oracle's estimate of quantity and scatter, and the actual quantity and scatter.
    >
    but the picture you're trying to invoke is probably the correct concept. We can safely assume that the
    re-organisation of the table has made it cheaper to use a brute-force method on the table (i.e. tablescan),
    and we can assume that he hasn't done anything to reduce the cost of the indexed access path in a
    similar way (and he may even have made it more expensive.) Well, that's a relief - I at least appear to be grasping the rudiments of the topic, in no small measure thanks
    to your chef d'oeuvre, Cost Based Oracle.
    Thanks
    Jonathan Lewis

  • Due to Upper() query not using Indexes.......

    Hi,
    I have query as under:
    SELECT max(A.REGION_ID)
      FROM SOP_REGION_COUNTRY_MAP  A,
           SOP_REGION_PRODLINE_MAP B,
           SOP_REGION_ACTIVITY_MAP C
    WHERE A.REGION_ID = B.REGION_ID
       AND A.REGION_ID = C.REGION_ID
       AND upper(trim(COUNTRY_NAME)) = upper(trim(:Var3))
       AND upper(trim(STATE_NAME)) = upper(trim(:Var2))
       AND upper(trim(PRODLINE_NAME)) = upper(trim(:Var1))
       AND A.BATCH_JOB_IND = 1
       AND B.BATCH_JOB_IND = 1The plan of the above query is as under:
         SELECT STATEMENT, GOAL = CHOOSE                                   Cost=7     Cardinality=1     Bytes=73
    SORT AGGREGATE                                                       Cardinality=1     Bytes=73
      NESTED LOOPS                                                  Cost=7     Cardinality=1     Bytes=73
       HASH JOIN                                                  Cost=6     Cardinality=1     Bytes=68
        TABLE ACCESS FULL     Object owner=SOP     Object name=SOP_REGION_COUNTRY_MAP     Cost=3     Cardinality=1     Bytes=25
        TABLE ACCESS FULL     Object owner=SOP     Object name=SOP_REGION_PRODLINE_MAP     Cost=3     Cardinality=1     Bytes=43
       INDEX RANGE SCAN     Object owner=SOP     Object name=FK1_SOP_REGION_ACTIVITY_MAP     Cost=2     Cardinality=48     Bytes=240Now, this query does full table access of sop_region_country_map and sop_region_prodline_map even though it has index on country_name,state_name and prodline_name columns but as i have used Upper function the index is not used. Now, I need this upper function as business req. states that none of the comparison should be missed jsut because user has entered country,state and prodline in mixed cases...
    Can you pls let me know what to do if i want to avoid this FTA and instaed use indexes.. without sacrificing Upper() functionlaity..?
    Thx

    okay...its something like query rewrite grant for user...
    when i give that...i can create functional index now..
    but still i can use trunc() for functional index...it tells me that functional index can be created only for pure function...what is pure and impure function in oracle.

Maybe you are looking for

  • Calendar Server Email Invitations

    I have Mavericks server set up solely for the calendar. My mail is hosted externally. I set up an [email protected] account on my external mail server specifically for the this calendar server to use. In the server app, I enabled "Enable invitations

  • Windows 7 install pendrive not showing in boot of Macbook Pro 3,1

    Hi, I have a 2007 Macbook Pro, and my superdrive has been broken for a while now, but because of work reasons I have to Install Windows 7 in it. I have an external Samsung DVD drive, and I have created several install pendrives with every tool known,

  • New macbook pro 15" won't detect external display using vga adapter

    Hi there I've tried multiple monitors and connectors but i can't get my mac to detect an external display. it responds as if nothing is connected. I'm fully up to date software-wise. any ideas? thanks for any help!!

  • How to set focus and mark red on certain select option field

    hi experts I embedded a select_option view in my application and  tried to use IF_WD_SELECT_OPTIONS->request_focus to set focus on a certain select option field if the logical check failed, and also hope the low field of the select option can be mark

  • Importing Excel or CSV fields into PDF

    Is it possible to import fields from excel files or CSV files?  I would like to have the answers and questions from my old PDF forms re-created with the new PDF 11 forms. Please help.