scan of the index systematic range

Hello

I read about the differences between the systematic index scan range, single scan, skip scan.

According to the docs, to how the CBO Evaluates in-list of iterators, http://docs.oracle.com/cd/B10500_01/server.920/a96533/opt_ops.htm

, I can see that

"The IN -list iterator is used when a query contains a IN clause with values." The execution plan is the same which would result for a statement of equality clause instead of IN with the exception of an extra step. This step occurs when the IN -list iterator feeds section of equality with the unique values of the IN -list. »

Of course, the doc is Oracle9i Database. (I do not find it in the docs of 11 g)

And the example 2-1 list iterators initial statement, shows that is used in the INDEX RANGE SCAN.


On my Oracle 11 GR 2 database, if I issue a statement similar to the example of the doc, so: select * from employees where employee_id in (7076, 7009, 7902), I see that it uses a SINGLE SCAN


On Oracle Performance Tuning: the Index access methods: Oracle Tuning Tip #11: Unique Index Scan , I read that

If Oracle should follow the Index Unique Scan, and then in SQL, equality operator (=) must be used. If any operator is used in other than op_Equality, then Oracle cannot impose this Unique Index Scan.

(and I think this sentence is somewhere in the docs also).

Thus, when using predicates in the list, why in my case Oracle used the unique scan on primary key column index? Because it wasn't a level playing field.

Thank you.

It is Internet... find us a lot of information a lot but don't know who to trust.

Exactly! It is thought, you should ALWAYS have in the back of your mind when you visit ANY site (no matter the author), read a book or document, listen to no matter WHAT presentation or read responses from forum (that's me included).

All sources of information can and will be errors, omissions and inaccuracies. An example which is used to illustrate a point can involve/suggest that it applies to the related points as well. It's just not possible to cover everything.

Your post doc 9i is a good example. The earliest records (even 7.3 always available online docs) often have a LOT of better explanations and examples of basic concepts. One of the reasons is that there were not nearly that many advanced concepts that explaining necessary; they did not exist.

michaelrozar17 just posted a link to a 12 c doc to refute my statement that the article you used was bad. No problem. Maybe this doc has been published because of these lines:

The database performs a unique sweep when the following conditions apply:

  • A query predicate refers to all columns in a unique index using an equality operator key, such as WHERE prod_id=10 .
  • A SQL statement contains a predicate of equality on a column referenced in an index created with the CREATE UNIQUE INDEX statement.

The authors mean that a single scan is ONLY performed for these conditions? We do not know. There could be several reasons that an INLIST ITERATOR has not been included in this list:

1. a LIST is NOT for this use case (what michaelrozar might suggest)

2. the authors were not aware that the CBO may also consider a unique analysis for a predicate INLIST

3. the authors WERE aware but forgot to include INLIST in the document

4. the authors were simply provide the conditions most common where a single sweep would be considered

We have no way of knowing what was the real reason. This does not mean that the document is not reliable.

In the other topic, I posted on the analysis of hard steps, site of BURLESON, and Jonathan contradicted me. If neither Burleson isn't reliable, do not know which author have sufficient credibility... of course, the two Burleson and Jonathan can say anything, it's true I can say anything, of course.

If site X is false, site is fake, Z site is fake... all people should read the documentation only and not other sites?

This is the BEST statement of reality to find the info I've seen displayed.

No matter who is the author, and what credibility that they could rely on the spent items you should ALWAYS keep these statements you comes to mind.

This means you need to do ' trust and verify. " You of 'trust', and then you "checked" and now have a conflict between WORDS and REALITY.

On those which is correct. If your reality is correct, the documentation is wrong. Ok. If your reality is wrong, then you know why.

Except that nobody has posted ANY REALITY that shows that your reality is wrong. IMHO, the reason for this is because the CBO probably MUCH, done a LOT of things that are not documented and that are never explored because there is never no reason to spend time exploring other than of curiosity.

You have not presented ANY reason to think that you are really concerned that a single scan is used.

Back to your original question:

Thus, when using predicates in the list, why in my case Oracle used the unique scan on primary key column index? Because it wasn't a level playing field.

1. why not use a single sweep?

2. what you want Oracle to use instead? A full table scan? A scan of the index systematic range? An index skip scan? A Full Scan index? An analysis of index full?

A full table scan?  For three key values? When there is a unique index? I hope not.

A scan of the index systematic range? Look a the doc 12 c provided for those other types of indexes

How the Index range scans work

In general, the process is as follows:

  1. Read the root block.
  2. Read the bundle branch block.
  3. Replacing the following steps until all data is retrieved:
    1. Read a block of sheets to get a rowid.

    2. Read a block to retrieve a table row.

. . .
For example, to analyze the index, the database moves backward or forward through the pads of sheets. For example, an analysis of identifications between 20 and 40 locates the first sheet block that has the lowest value of key that is 20 or more. The analysis produced horizontally through the linked list nodes until it finds a value greater than 40 and then stops.

If that '20' was the FIRST index value and the '40' was the LAST one who reads ALL of the terminal nodes. That doesn't look good for me.

How to index full scans of work

The database reads the root block and then sailed on the side of the index (right or left hand if do a descending full scan) until it reaches a block of sheets. The database then reads down the index, one block at a time, in a sorted order. The analysis uses single e/s rather than I/O diluvium.

Which is about as the last example is not?

How to index Fast Full Scans work

The database uses diluvium I/O to read the root block and all the blocks of leaf and branch. Databases don't know branch blocks and the root and reads the index on blocks of leaves entries.

Seems not much better than the last one for your use case.

Skip index scans

An index skip scan occurs when the first column of a composite index is "skipped" or not specified in the query.

. . .

How Index Skip scan work

An index skip scan logically divides a composite index in smaller subindex. The number of distinct values in the main columns of the index determines the number of logical subindex. The more the number, the less logical subindex, the optimizer should create, and becomes the most effective analysis. The scan reads each logical index separately and "jumps" index blocks that do not meet the condition of filter on the column no leader.

Which does not apply to your use cases; you do not have a composite index, and there is nothing to jump. If Oracle were to 'jump' between the values of the list in it would be still reads these blocks 'inbetween' and them to jump.

Which brings back us to the using a single scan, one at a time, for each of the values in the list in. The root index block will be in the cache after the first value lies, so it only needs to be read once. After that just Oracle detects that the entry of only ONE necessary index. Sounds better than any other variants for me if you are only dealing with a small number of values in the IN clause.

Tags: Database

Similar Questions

  • compress the index

    Hello
    Compressing my indexes improve performance or decrease? When it will use exactly

    Dear user1175505,

    Online documentation of the Oracle;

    +"+
    + Using Compression of Index +.

    + Bitmap indexes are always stored as patented, compressed without the need for user intervention. B-tree indexes, however, can be stored specifically compressed way to allow huge space saving, storing more keys in each index block, which also leads to less i/o and better performance. +

    + Compression key allows you to compress an index B-tree, which reduces the overhead of repeated values storage. In the case of a non-unique index, all indexes on columns can be stored in a compressed format, while in the case of a unique index, at least one index column must be kept not compressed. +

    + In general, the an index keys have two pieces, a piece of group and a unique piece. If the key is not set to have a unique piece, Oracle provides a in the form of a rowid annexed to the pool room. Key compression is a method of breaking the pool room and store it so it can be shared by several unique pieces. The cardinality of the columns selected must be compressed determines the compression ratio that can be achieved. Thus, for example, if a unique index, which consists of five columns providing the uniqueness mainly the last two columns, it is more optimal to choose three columns to be stored compressed. If you choose to compress the four columns, the repetition will have almost disappeared, and the compression ratio will be worse. +

    * + Key compression reduces storage of an index, but it can increase the time processor required to rebuild the key during a scan of the index column values. He faces also certain additional storage overhead, because each prefix entry has an overload of four bytes associated with it. + *

    + Indexes Local versus Global index +.

    + Index B-tree on the partitioned tables can be global or local. With Oracle8i, and earlier versions, Oracle has recommended that global indexes will not be used in data warehouse environments, because a partition DDL statement (for example, ALTER TABLE...) DROP PARTITION) would invalidate the entire index, and the index rebuilding is expensive. Since the Oracle 10 g database, global index can be maintained without Oracle marking them as unusable after the DDL. This improvement makes overall more efficient index for data warehouse environments. +

    + However, index will be more common than the overall index. Global indexes must be used when there is a specific requirement that cannot be met by local indexes (for example, a unique index on a no partitioning key or a requirement of performance). +

    + Bitmap indexes on partitioned tables are always local. +
    +"+

    Ogan

  • Best preferences for queries to prefix with the index catalog (CTXCAT)

    Documentation for Oracle Text gives this example of a setting preferred prefix/substring for the index catalog and context:

    Start
    ctx_ddl.create_preference ('mywordlist', 'BASIC_WORDLIST');
    ctx_ddl.set_attribute ('mywordlist', 'PREFIX_INDEX', 'TRUE');
    ctx_ddl.set_attribute ('mywordlist', 'PREFIX_MIN_LENGTH', ' 3');
    ctx_ddl.set_attribute ('mywordlist', 'PREFIX_MAX_LENGTH', ' 4');
    ctx_ddl.set_attribute ('mywordlist', 'SUBSTRING_INDEX', 'YES');
    end;

    The SUBSTRING_INDEX attribute is really necessary if I only ever issue that research prefix, such as:

    Auction title SELECT FROM WHERE CATSEARCH (title, ' cam *', ") > 0;

    I'm not sure that you understand the difference between the PREFIX_INDEX and the SUBSTRING_INDEX.

    Substring is intended to speed up searches "double truncation", especially for the requirements specialist such as the research of the chemical name, where you want to search "% fluoro" or similar.

    It is NOT recommended for general use, because it significantly slows down indexing and makes the very much larger indices.

    Prefix allows you to speed up the search for right truncated simple searches such as '% of cam', but it's not normally necessary.

    For general use with middle office truncation and right (for example "oracl %" or "% key ora") I would not use one of these options. Double truncation or truncation on the left ("% racl %" or "% scrapes") should be avoided as far as possible - use of the wildcard character to start without the option of substring will cause a full table scan on the index table $I to find all words that match, given that the index can not be used with a wildcard to start.

  • Partitioned global index on partitioned table range, but the index partition does not work

    Hello:

    I was creating an index partitioned on table partitioned and partitioned index does not work.

    create table table_range)

    CUST_FIRST_NAME VARCHAR2 (20).

    CUST_GENDER CHAR (1),

    CUST_CITY VARCHAR2 (30),

    COUNTRY_ISO_CODE CHAR (2),

    COUNTRY_NAME VARCHAR2 (40),

    COUNTRY_SUBREGION VARCHAR2 (30),

    PROD_ID NUMBER NOT NULL,

    CUST_ID NUMBER NOT NULL,

    TIME_ID DATE NOT NULL,

    CHANNEL_ID NUMBER NOT NULL,

    PROMO_ID NUMBER OF NON-NULL,

    QUANTITY_SOLD NUMBER (10.2) NOT NULL,

    AMOUNT_SOLD NUMBER (10.2) NOT NULL

    )

    partition by (range (time_id)

    lower partition p1 values (u01 tablespace to_date('2001/01/01','YYYY/MM/DD')),

    lower partition (to_date('2002/01/01','YYYY/MM/DD')) tablespace u02 p2 values

    );

    create index ind_table_range on table2 (prod_id)

    () global partition range (prod_id)

    values less than (100) partition p1,

    lower partition p2 values (maxvalue)

    );

    SQL > select TABLE_NAME, SUBPARTITION_COUNT, HIGH_VALUE, nom_partition NUM_ROWS of user_tab_partitions;

    TABLE_NAME NOM_PARTITION SUBPARTITION_COUNT HIGH_VALUE NUM_ROWS

    ----------- ---------------- ------------------ -------------------------------------------------------------------------------- ----------

    TABLE_RANGE P2 0 TO_DATE (' 2002-01-01 00:00:00 ',' SYYYY-MM-DD HH24:MI:SS ',' NLS_CALENDAR = GREGORIA 259418)

    TABLE_RANGE P1 0 TO_DATE (' 2001-01-01 00:00:00 ',' SYYYY-MM-DD HH24:MI:SS ',' NLS_CALENDAR = GREGORIA 659425)

    SQL > select INDEX_NAME, NUM_ROWS nom_partition, HIGH_VALUE user_ind_partitions;

    INDEX_NAME NOM_PARTITION HIGH_VALUE NUM_ROWS

    ------------------------------ ------------------------------ -------------------------- ----------

    P1 IND_TABLE_RANGE 100 479520

    IND_TABLE_RANGE P2 MAXVALUE 439323

    SQL > EXECUTE DBMS_STATS. GATHER_TABLE_STATS (USER, 'TABLE_RANGE');

    SQL > EXECUTE DBMS_STATS. GATHER_TABLE_STATS (USER, 'TABLE_RANGE', GRANULARITY = > 'PARTITION');

    SQL > EXECUTE DBMS_STATS. GATHER_INDEX_STATS (USER, 'IND_TABLE_RANGE');

    SQL > EXECUTE DBMS_STATS. GATHER_INDEX_STATS (USER, 'IND_TABLE_RANGE', GRANULARITY = > 'PARTITION');

    SQL > set autotrace traceonly

    SQL > alter shared_pool RAS system;

    SQL > changes the system built-in buffer_cache;

    SQL > select * from table_range

    where prod_id = 127;

    ---------------------------------------------------------------------------------------------------

    | ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time | Pstart. Pstop |

    ---------------------------------------------------------------------------------------------------

    |   0 | SELECT STATEMENT |             | 16469 |  1334K |  3579 (1) | 00:00:43 |       |       |

    |   1.  RANGE OF PARTITION ALL THE |             | 16469 |  1334K |  3579 (1) | 00:00:43 |     1.     2.

    |*  2 |   TABLE ACCESS FULL | TABLE_RANGE | 16469 |  1334K |  3579 (1) | 00:00:43 |     1.     2.

    ---------------------------------------------------------------------------------------------------

    Information of predicates (identified by the operation identity card):

    ---------------------------------------------------

    2 - filter ("PROD_ID" = 127)

    Statistics

    ----------------------------------------------------------

    320 recursive calls

    2 db block Gets

    13352 consistent gets

    11820 physical reads

    0 redo size

    855198 bytes sent via SQL * Net to client

    12135 bytes received via SQL * Net from client

    1067 SQL * Net back and forth to and from the client

    61 sorts (memory)

    0 sorts (disk)

    15984 rows processed

    Once the sentence you say ' does not ' and then you go to paste plans that seem to show that it "works".

    What gives?

    In fact, if you look at the plans - think Oracle you have 16 k rows in the table and he'll be back k 12 rows for your select statement. In this case, Oracle is picking up the right plan - full scan 16 ranks of k is a lot less work to digitize the index lines k 12 followed by the research of rank k 12 rowid.

  • doubt about the Index Skip Scan

    Hi all

    I read the setting of Oracle performance guide (Version 11.2 Chapter 11). I just want to see index skip scan with an example. I created a table called t and inserted the test data. When I asked the table optimizer did not use the index skip scan path.

    Can you please let me know what mistake I am doing here.

    Thanks a lot for your help in advance.

    SQL > create table t (empno number
    2, ename varchar2 (2000)
    3, varchar2 (1) sex
    4, email_id varchar2 (2000));

    Table created

    SQL >
    SQL >-test data
    SQL > insert into t
    2 level, select "suri" | (level), ','suri.king' | level | ' @gmail.com'
    3 double
    4. connect by level < = 20000
    5.

    20000 lines inserted

    SQL >
    SQL > insert into t
    2 Select level + 20000, 'surya ' | (level + 20000), 'F', 'surya.princess'. (level + 20000) : ' @gmail.com '
    3 double
    4. connect by level < = 20000
    5.

    20000 lines inserted

    SQL > create index t_gender_email_idx on t (gender, email_id);

    Index created

    SQL > explain the plan for
    2 Select
    3 t
    4 where email_id = "[email protected]";

    He explained.

    SQL > select *.
    table 2 (dbms_xplan.display);

    PLAN_TABLE_OUTPUT
    ----------------------------------------------------------------------------------------------------------------
    Hash value of plan: 1601196873

    --------------------------------------------------------------------------
    | ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
    --------------------------------------------------------------------------


    |   0 | SELECT STATEMENT |      |     4.  8076 |   103 (1) | 00:00:02 |
    |*  1 |  TABLE ACCESS FULL | T    |     4.  8076 |   103 (1) | 00:00:02 |
    --------------------------------------------------------------------------

    Information of predicates (identified by the operation identity card):
    ---------------------------------------------------

    1 - Filter ("EMAIL_ID"= "[email protected]")

    Note
    -----
    -dynamic sample used for this survey (level = 2)

    17 selected lines.

    See you soon,.

    Suri

    You have just demonstrated how your execution plan gets screwed up if you do not have your statistics

    SQL > create table t
    () 2
    3 empno number
    4, ename varchar2 (2000)
    5, varchar2 (1) sex
    6, email_id varchar2 (2000)
    7  );

    Table created.

    SQL > insert into t
    2 Select level, "suri" | (level), ', 'suri.king'| level | ' @gmail.com'
    3 double
    4. connect by level<=>
    5.

    20000 rows created.

    SQL > insert into t
    2 Select level + 20000, 'surya ' | (level + 20000), 'F', 'surya.princess'. (level + 20000) : ' @gmail.com'
    3 double
    4. connect by level<=>
    5.

    20000 rows created.

    SQL > create index t_gender_email_idx on t (gender, email_id);

    The index is created.

    SQL > set autotrace traceonly explain
    SQL >
    SQL > select *.
    2 t
    3 where email_id = "[email protected]";

    Execution plan
    ----------------------------------------------------------
    Hash value of plan: 2153619298

    --------------------------------------------------------------------------
    | ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |      |     3.  6057.    79 (4) | 00:00:01 |
    |*  1 |  TABLE ACCESS FULL | T    |     3.  6057.    79 (4) | 00:00:01 |
    --------------------------------------------------------------------------

    Information of predicates (identified by the operation identity card):
    ---------------------------------------------------

    1 - Filter ("EMAIL_ID"= "[email protected]")

    Note
    -----
    -dynamic sampling used for this statement

    SQL > exec dbms_stats.gather_table_stats (user, 't', cascade-online true)

    PL/SQL procedure successfully completed.

    SQL > select *.
    2 t
    3 where email_id = "[email protected]";

    Execution plan
    ----------------------------------------------------------
    Hash value of plan: 2655860347

    --------------------------------------------------------------------------------------------------
    | ID | Operation | Name               | Lines | Bytes | Cost (% CPU). Time |
    --------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |                    |     1.    44.     1 (0) | 00:00:01 |
    |   1.  TABLE ACCESS BY INDEX ROWID | T                  |     1.    44.     1 (0) | 00:00:01 |
    |*  2 |   INDEX SKIP SCAN | T_GENDER_EMAIL_IDX |     1.       |     1 (0) | 00:00:01 |
    --------------------------------------------------------------------------------------------------

    Information of predicates (identified by the operation identity card):
    ---------------------------------------------------

    2 - access ("EMAIL_ID"= '[email protected]')
    filter ("EMAIL_ID"= "[email protected]")

    SQL >

  • The index on a book page ranges

    I have a catalog (several InDesign documents organized in a book) and I have generated my index.  I noticed that some of the page ranges do like this:

    Furniture... 4-5, 6-7, 10, 12-13

    I need it to be:

    Funiture... 4-7, 10, 12-13

    It does this (I thought) is because 'Furniture' is indexed on two separate documents in the book.

    So, I deleted the second index entry and changed the premiera (at pages 4-5) to be 'for the next number of pages"and specified the number to 2 pages.

    Now it reads:

    Furniture... 4-5, 10, 12-13

    How can I get the index to combine the two entrances on two separate documents in a book?

    Thanks in advance for your comments.

    InDesign is ever going to do it for you, you'll have to do that yourself. But this script: http://www.kahrel.plus.com/indesign/index_update.html can make your life much easier.

    Peter

  • FULL TABLE SCAN even with the index, but why?

    Could someone please explain why I'd get FULL TABLE SCAN explain plan results when joining 2 tables on columns that already have clues about them? For example,.
    consider this fictional scenario:

    employee table with columns:
    employee # (primary key column)
    name

    address table with columns:
    employee # (foreign key to employee.employee #)
    subscription_type
    address

    Select Employee.Name since it is, address.address_type, address.address
    where employee.employee # = address.employee #.

    This query shows a full table scan in terms of the explain command.

    Full scan of the table is not necessarily slow and index access is not necessarily fast.

    You will recover, no doubt, most if not all the ranks on both sides. The fastest way to retrieve each row in a table is to do a table scan. Using an index, and a single block of reading for each row in a table is much less effective than to do a table scan.

    Justin

  • Invalidation of the index based on a function because the recompilation

    Hello

    one of our customers has two indices according to the functions that fall under the State "off" in some situations. After looking more closely at the situation, there are some things that my opinion are different from what I expected of a function-based index. Because I am unable to find anything about either on metalink (or I'm not asking the right question) I would appreciate a second opinion of you.

    To keep things simple, I gave an example to illustrate the behavior. I use Oracle 12.1.0.2, although it can also be reproduced on versions 10.2 and 11.2.

    It's my environment and three parameters that I find relevant to the discussion:

    SQL> select banner from v$version;
    
    BANNER
    ----------------------------------------------------------------------------
    
    Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
    PL/SQL Release 12.1.0.2.0 - Production
    CORE    12.1.0.2.0      Production
    TNS for Linux: Version 12.1.0.2.0 - Production
    NLSRTL Version 12.1.0.2.0 - Production
    
    SQL> show parameter remote_dependencies
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ----------
    remote_dependencies_mode             string      TIMESTAMP
    
    SQL> show parameter query_rewrite
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- -------------
    query_rewrite_enabled                string      TRUE
    query_rewrite_integrity              string      enforced
    

    Test case:

    SQL> CREATE OR REPLACE FUNCTION f1 (p_string IN VARCHAR2)
      2  RETURN VARCHAR2
      3  DETERMINISTIC
      4  IS
      5  BEGIN
      6    RETURN lower(p_string);
      7  END f1;
      8  /
    
    Function created.
    
    SQL> CREATE TABLE tmp_t1 (a_string VARCHAR2(10));
    
    Table created.
    
    SQL> INSERT INTO tmp_t1 VALUES ('a');
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> CREATE INDEX x1_tmp_t1 ON tmp_t1(f1(a_string));
    
    Index created.
    
    SQL> set linesize 80;
    SQL> column index_name format a10;
    SQL> SELECT index_name, index_type, status, funcidx_status
      2    FROM user_indexes;
    
    INDEX_NAME INDEX_TYPE                  STATUS   FUNCIDX_
    ---------- --------------------------- -------- --------
    X1_TMP_T1  FUNCTION-BASED NORMAL       VALID    ENABLED
    

    We have our table and our based on an index function which basically converts the values to lowercase. From here on things, download a little weird. What happens with the index based on a function if the underlying function is recompiled? I always thought (and which is also stated in the Concepts and the use of function index (Doc ID 66277.1)) that the index would change its status to "disabled". Here is an excerpt of the said Doc ID:

    The index depends on the State of the PL/SQL function. The index can be

    struck down or rendered useless by changes to the function. The index is marked

    People with DISABILITIES, if he is brought to the function or function is re-created.

    The timestamp of the function is used to validate the index.

    To allow the index after it is created, the function if the signature of the

    the function is identical to the front:

    ALTER INDEX ENABLE;

    If the signature of functions is changed, to make the changes effective

    in the index, the index must be renewed to make it valid.

    ALTER INDEX REBUILD.

    It seems that this is not the case, as the index remains valid and activate.

    SQL> alter function f1 compile;
    
    Function altered.
    
    SQL> SELECT index_name, index_type, status, funcidx_status
      2    FROM user_indexes;
    
    INDEX_NAME INDEX_TYPE                  STATUS   FUNCIDX_
    ---------- --------------------------- -------- --------
    X1_TMP_T1  FUNCTION-BASED NORMAL       VALID    ENABLED
    

    OK, explicitly recompiling function F1 single timestamp changed. What if we replace the function completely and we change the output of the function - for example we will switch from a LOWER function to SUPERIOR function in the body of the F1. Again, it is change that I thought would be not only to disable the index based on a function, but also force its reconstruction. At least that is my understanding of the explanation in Doc ID).

    SQL> CREATE OR REPLACE FUNCTION f1 (p_string IN VARCHAR2)
      2  RETURN VARCHAR2
      3  DETERMINISTIC
      4  IS
      5  BEGIN
      6    RETURN UPPER(p_string);
      7  END f1;
      8  /
    
    Function created.
    
    SQL> SELECT index_name, index_type, status, funcidx_status
      2    FROM user_indexes;
    
    INDEX_NAME INDEX_TYPE                  STATUS   FUNCIDX_
    ---------- --------------------------- -------- --------
    X1_TMP_T1  FUNCTION-BASED NORMAL       VALID    ENABLED
    
    

    Should not be. Because of the function "create or replace" F1 never go through a "invalid" phase which may be necessary for index becomes unusable? What about queries on the TMP_T1 table? Does optimizer always uses access index or not? What about the results?

    SQL> EXPLAIN PLAN SET statement_id='s1' FOR
      2  SELECT a_string, f1(a_string) as f1_a_string, f1('a') as f1_literal
      3    FROM tmp_t1
      4   WHERE f1(a_string) = 'a';
    
    Explained.
    
    SQL> SELECT * from table(dbms_xplan.display(statement_id=>'s1'));
    
    PLAN_TABLE_OUTPUT                                                                                                   
    ------------------------------------------------------------------------------------------------------------------------
    Plan hash value: 3133804460                                                                                         
                                                                                                                        
    -------------------------------------------------------------------------------------------------                   
    | Id  | Operation                           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |                   
    -------------------------------------------------------------------------------------------------                   
    |   0 | SELECT STATEMENT                    |           |     1 |  2024 |     2   (0)| 00:00:01 |                   
    |   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TMP_T1    |     1 |  2024 |     2   (0)| 00:00:01 |                   
    |*  2 |   INDEX RANGE SCAN                  | X1_TMP_T1 |     1 |       |     1   (0)| 00:00:01 |                   
    -------------------------------------------------------------------------------------------------
    

    The index is used by the optimizer, see the results.

    SQL> column f1_a_string format a15;
    SQL> column f1_literal format a15;
    SQL> SELECT a_string, f1(a_string) as f1_a_string, f1('a') as f1_literal
      2    FROM tmp_t1
      3   WHERE f1(a_string) = 'a';
    
    A_STRING   F1_A_STRING     F1_LITERAL
    ---------- --------------- ---------------
    a          a               A
    

    A_STRING = value in the table

    F1_A_STRING = value of f1 (a_string) but the value is not evaluated because it comes from an index, so tiny value (remember, at the time index created the function returned small values)

    F1_LITERAL = value of the function f1 newly evaluated, using literal instead of the value in the table.

    Predicate f1 (a_string) = 'a' should return no rows because no character uppercase is equivalent to "a". Query with f1 (a_string) = 'A' should return a line, but it doesn't.

    SQL> SELECT a_string, f1(a_string) as f1_a_string, f1('a') as f1_literal
      2    FROM tmp_t1
      3   WHERE f1(a_string) = 'A';
    
    no rows selected
    

    Anyone know if this is an expected behavior? And, is it possible to disable the index based on a function whenever the underlying function signature is changed? The parameter query_rewrite_integrity = applied from

    DOC-ID 66277.1 does not seem to do the trick:

    (c) session variables

    ~~~~~~~~~~~~~~~~~~~~

    QUERY_REWRITE_ENABLED (true, false),

    QUERY_REWRITE_INTEGRITY (confidence, forced, stale_tolerated)

    determines the optimizer to use index based on a function with

    expressions using SQL, user defined functions functions.

    TRUST: Oracle allows rewrites using relationships that have

    was declared.

    APPLIED: Oracle ensures and guarantees consistency and integrity.

    STALE_TOLERATED: Oracle allows rewrites using vessels of the relationship not applied.

    Used in the case of materialized views.

    Set session variable cost function optimizer to choose the

    a function-based index

    Kind regards

    SAMO

    From the Manual 11.2 ( https://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_indexes.htm#ADFNS254 )

    "If you change the semantics of a DETERMINISTIC run and recompile, then you must manually rebuild all addicts depending on index and materialized views." Otherwise, they report results for the previous version of the function. »

    This note is not that I made my initial comment well - which was based on an incorrect memory the relationship between function-oriented and autonomous pl/sql functions, so I won't try to explain it. In fact, I went back to Oracle 8i practice to see if something had changed between yesterday and today and found that I had described exactly the behavior that the OP has been seeing. It's the way it is supposed to be.

    Concerning

    Jonathan Lewis

  • The index used only when given Index indicator

    Hello

    Version of RDBMS - 11.2.0.3.0

    I have a situation where only when I use the Index indicator, index does is used.

    Use case: -.

    1. SELECT query on a table with about 100 KB of data.

    2. have the index on the column that is used in the WHERE clause of the SELECT query.

    CREATE TABLE him_entity (id NUMBER, him_val CHAR(1));
    
    
    INSERT INTO him_entity
    SELECT rownum,'1' FROM dual CONNECT BY level<=1000000;
    
    
    CREATE INDEX idx_him_val ON him_entity(him_val);
    
    
    
    
    
    

    Without using Index indicator, Explain plan: -.

    SELECT ID 
    FROM him_entity
    WHERE him_val='1';
    
    
    -----------------------------------------------------------------------------------
    | Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |               |  1000K|  4882K|   498   (5)| 00:00:06 |
    |*  1 |  TABLE ACCESS FULL| HIM_ENTITY    |  1000K|  4882K|   498   (5)| 00:00:06 |
    -----------------------------------------------------------------------------------
    
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    
       1 - filter("HIM_VAL"='1')
    

    With the help of Index indicator, explain the plan: -.

    SELECT /*+ index(him_entity idx_him_val)*/ ID 
    FROM him_entity
    WHERE him_val='1';
    
    
    ---------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |               |  1000K|  4882K|  3485   (1)| 00:00:42 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| HIM_ENTITY    |  1000K|  4882K|  3485   (1)| 00:00:42 |
    |*  2 |   INDEX RANGE SCAN          | IDX_HIM_VAL   |  1000K|       |  1824   (1)| 00:00:22 |
    ---------------------------------------------------------------------------------------------
    
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    
       2 - access("HIM_VAL"='1')
    

    (1) could you explain why Index was not be picked up without indicator Index for help?

    (2) I gathered statistics for the table before running the query.

    (3) is it fine / safe to use the FIRST_ROWS hint instead of Index indicator?

    Thank you...

    1. SELECT THE ID
    2. OF him_entity
    3. WHERE him_val = '1';

    You select all the rows in the table.

    As your query will extract all lines then the optimal trajectory IS FULL TABLE SCAN instead of using INDEXES

    If we let you use less than 5% of table rows, and then using index can be an optimal trajectory to go for the record.

    1. SELECT / * + index (him_entity idx_him_val) * / ID
    2. OF him_entity
    3. WHERE him_val = '1';

    Your strength of indicator Index to fetch the file by using the index of the query

  • The index of the first State UNUSABLE.

    Hi my current version of the DB is version 11.2.0.3.0 Oracle.

    In one of the old environment (Release 10.2.0.4.0), I found one of the query works fine (about 4 minutes) while the same get expired (~ 30 minutes) in the current version(11g).

    After analysis found that in 10g environment its going for scan limited index, but 11g a its goes for FTS of the same table.
    Then I tried to force the flag for 11g environment and got below error.

    ERROR on line 1:
    ORA-01502: index 'INV_ID1' or partition of this index is unusable

    But when I tried to understand the usual State status, its display n/a, index partitioned index.
    I checked the status column of DBA_IND_PARTITION for all partitions 62 specific for the index INV_ID1, its display "n/a".
    So my question is how can I find the UNUSABLE State of this/other index in my database and repair?

    The index above is local partitioned with 62 partitions. Here is the comparison of the plan.
    10g:
    ------------------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                             | Name                 | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
    ------------------------------------------------------------------------------------------------------------------------------------------------------------
    |   1 |  TABLE ACCESS BY INDEX ROWID          | pi                   |      0 |      1 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
    |*  2 |   INDEX UNIQUE SCAN                   | pi_PKI               |      0 |      1 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
    |   3 |  SORT ORDER BY                        |                      |      1 |    500 |      0 |00:04:30.17 |   95321 |   4557 |  1024 |  1024 |          |
    |*  4 |   COUNT STOPKEY                       |                      |      1 |        |      0 |00:04:30.17 |   95321 |   4557 |       |       |          |
    |   5 |    PARTITION RANGE ALL                |                      |      1 |  46695 |      0 |00:04:30.17 |   95321 |   4557 |       |       |          |
    |   6 |     PARTITION HASH ALL                |                      |     62 |  46695 |      0 |00:04:30.17 |   95321 |   4557 |       |       |          |
    |*  7 |      TABLE ACCESS BY LOCAL INDEX ROWID| INV                  |    496 |  46695 |      0 |00:04:30.16 |   95321 |   4557 |       |       |          |
    |*  8 |       INDEX RANGE SCAN                | INV_ID1              |    496 |  47220 |  48147 |00:00:16.70 |    2202 |    309 |       |       |          |
    ------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    11g:
    --------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name                 | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
    --------------------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |                      |      1 |        |    396 |00:30:34.02 |   86M|      8265K|       |       |          |
    |   1 |  TABLE ACCESS BY INDEX ROWID| pi                   |      6 |      1 |      6 |00:00:00.01 |   20 |         0 |       |       |          |
    |*  2 |   INDEX UNIQUE SCAN         | pi_PKI               |      6 |      1 |      6 |00:00:00.01 |   14 |         0 |       |       |          |
    |   3 |  SORT ORDER BY              |                      |      1 |    500 |    396 |00:30:34.02 |   86M|      8265K| 86016 | 86016 |75776  (0)|
    |*  4 |   COUNT STOPKEY             |                      |      1 |        |    396 |00:30:34.02 |   86M|      8265K|       |       |          |
    |   5 |    PARTITION RANGE ALL      |                      |      1 |    500 |    396 |00:30:34.02 |   86M|      8265K|       |       |          |
    |   6 |     PARTITION HASH ALL      |                      |     62 |    500 |    396 |00:30:34.02 |   86M|      8265K|       |       |          |
    |*  7 |      TABLE ACCESS FULL      | INV                  |    496 |    500 |    396 |00:30:34.01 |   86M|      8265K|       |       |          |
    --------------------------------------------------------------------------------------------------------------------------------------------------

    ORA-01502: index 'String' or a partition of this index is unusable

    Cause: You tried to access an index or an index partition that has been marked unusable by a direct load or by a DDL operation

    Action: REMOVE the index specified, REBUILD the specified index or REBUILD the unusable index partition

  • Rebuild the Index

    Hello
    the following query takes more than 3 hours.

    the wait event is a clue: PSCRECV_HDR. Should rebuild us this index? Or problem is something else?
    How can I check the health of the index?
    show parameter optimizer
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------
    optimizer_capture_sql_plan_baselines boolean     FALSE
    optimizer_dynamic_sampling           integer     2
    optimizer_features_enable            string      11.2.0.3
    optimizer_index_caching              integer     0
    optimizer_index_cost_adj             integer     100
    optimizer_mode                       string      ALL_ROWS
    optimizer_secure_view_merging        boolean     TRUE
    optimizer_use_invisible_indexes      boolean     FALSE
    optimizer_use_pending_statistics     boolean     FALSE
    optimizer_use_sql_plan_baselines     boolean     TRUE
    
    Explain plan for
    SELECT A.BUSINESS_UNIT, D.DESCR FROM PS_SP_RECV1_NONVW A, PS_SP_RCV1_NONVWLN D WHERE D.BUSINESS_UNIT LIKE 'I%' AND D.BUSINESS_UNIT=A.BUSINESS_UNIT AND D.LANGUAGE_CD='FRA' UNION SELECT  BUSINESS_UNIT, DESCR FROM PS_SP_RECV1_NONVW A WHERE BUSINESS_UNIT LIKE 'IF%' AND NOT EXISTS (SELECT 'X' FROM PS_SP_RCV1_NONVWLN D WHERE  D.BUSINESS_UNIT=A.BUSINESS_UNIT AND 
    
    explain plan succeeded.
    159 ms 
    PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                            
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
                                                                                                                                                                                                                                                                                                                 
    -----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        
    | Id  | Operation                         | Name               | Rows  | Bytes |TempSpc| Cost (%CPU)|                                                                                                                                                                                                        
    -----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        
    |   0 | SELECT STATEMENT                  |                    |  9960M|   538G|       |   313M  (1)|                                                                                                                                                                                                        
    |   1 |  SORT ORDER BY                    |                    |  9960M|   538G|   410G|   313M  (1)|                                                                                                                                                                                                        
    |   2 |   SORT UNIQUE                     |                    |  9960M|   538G|   633G|   188M  (1)|                                                                                                                                                                                                        
    |   3 |    UNION-ALL                      |                    |       |       |       |            |                                                                                                                                                                                                        
    |*  4 |     HASH JOIN                     |                    |  9960M|   538G|  3944K| 31301  (98)|                                                                                                                                                                                                        
    |*  5 |      INDEX FAST FULL SCAN         | PSCRECV_HDR        |   201K|  1577K|       |   187   (2)|                                                                                                                                                                                                        
    |*  6 |      HASH JOIN                    |                    | 98659 |  4817K|       |   191   (2)|                                                                                                                                                                                                        
    |   7 |       NESTED LOOPS                |                    |       |       |       |            |                                                                                                                                                                                                        
    |   8 |        NESTED LOOPS               |                    |     1 |    42 |       |     3   (0)|                                                                                                                                                                                                        
    |   9 |         MERGE JOIN CARTESIAN      |                    |     1 |    12 |       |     2   (0)|                                                                                                                                                                                                        
    |* 10 |          INDEX RANGE SCAN         | PS_BUS_UNIT_TBL_FS |     1 |     6 |       |     1   (0)|                                                                                                                                                                                                        
    |  11 |          BUFFER SORT              |                    |     1 |     6 |       |     1   (0)|                                                                                                                                                                                                        
    |* 12 |           INDEX RANGE SCAN        | PS_BUS_UNIT_TBL_FS |     1 |     6 |       |     1   (0)|                                                                                                                                                                                                        
    |* 13 |         INDEX UNIQUE SCAN         | PS_BUS_UNIT_LANG   |     1 |       |       |     0   (0)|                                                                                                                                                                                                        
    |  14 |        TABLE ACCESS BY INDEX ROWID| PS_BUS_UNIT_LANG   |     1 |    30 |       |     1   (0)|                                                                                                                                                                                                        
    |* 15 |       INDEX FAST FULL SCAN        | PSCRECV_HDR        |   201K|  1577K|       |   187   (2)|                                                                                                                                                                                                        
    |* 16 |     FILTER                        |                    |       |       |       |            |                                                                                                                                                                                                        
    |* 17 |      HASH JOIN                    |                    |   100K|  3450K|       |   190   (2)|                                                                                                                                                                                                        
    |  18 |       TABLE ACCESS BY INDEX ROWID | PS_BUS_UNIT_TBL_FS |     1 |    27 |       |     2   (0)|                                                                                                                                                                                                        
    |* 19 |        INDEX RANGE SCAN           | PS_BUS_UNIT_TBL_FS |     1 |       |       |     1   (0)|                                                                                                                                                                                                        
    |* 20 |       INDEX FAST FULL SCAN        | PSCRECV_HDR        |   201K|  1577K|       |   187   (2)|                                                                                                                                                                                                        
    |  21 |      NESTED LOOPS                 |                    |  9178 |   215K|       |   681   (1)|                                                                                                                                                                                                        
    |  22 |       NESTED LOOPS                |                    |     1 |    16 |       |     0   (0)|                                                                                                                                                                                                        
    |* 23 |        INDEX UNIQUE SCAN          | PS_BUS_UNIT_LANG   |     1 |    10 |       |     0   (0)|                                                                                                                                                                                                        
    |* 24 |        INDEX UNIQUE SCAN          | PS_BUS_UNIT_TBL_FS |     1 |     6 |       |     0   (0)|                                                                                                                                                                                                        
    |* 25 |       INDEX RANGE SCAN            | PSCRECV_HDR        |  9178 | 73424 |       |   681   (1)|                                                                                                                                                                                                        
    -----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                 
    Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
    ---------------------------------------------------                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                 
       4 - access("A"."BUSINESS_UNIT"="A"."BUSINESS_UNIT" AND                                                                                                                                                                                                                                                    
                  "A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT")                                                                                                                                                                                                                                                       
       5 - filter("A"."RECV_STATUS"<>'C' AND "A"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                      
       6 - access("A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT")                                                                                                                                                                                                                                                       
      10 - access("B"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                                                 
           filter("B"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                                                 
      12 - access("B"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                                                 
           filter("B"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                                                 
      13 - access("B"."BUSINESS_UNIT"="C"."BUSINESS_UNIT" AND "C"."LANGUAGE_CD"='FRA')                                                                                                                                                                                                                           
           filter("C"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                                                 
      15 - filter("A"."RECV_STATUS"<>'C' AND "A"."BUSINESS_UNIT" LIKE 'I%')                                                                                                                                                                                                                                      
      16 - filter( NOT EXISTS (SELECT 0 FROM SYSADM."PS_BUS_UNIT_LANG"                                                                                                                                                                                                                                           
                  "C",SYSADM."PS_BUS_UNIT_TBL_FS" "B",SYSADM."PS_RECV_HDR" "A" WHERE                                                                                                                                                                                                                             
                  "A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT" AND "A"."RECV_STATUS"<>'C' AND                                                                                                                                                                                                                         
                  "A"."BUSINESS_UNIT"=:B1 AND "B"."BUSINESS_UNIT"=:B2 AND                                                                                                                                                                                                                                        
                  "B"."BUSINESS_UNIT"="C"."BUSINESS_UNIT" AND "C"."LANGUAGE_CD"='FRA' AND                                                                                                                                                                                                                        
                  "C"."BUSINESS_UNIT"=:B3))                                                                                                                                                                                                                                                                      
      17 - access("A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT")                                                                                                                                                                                                                                                       
      19 - access("B"."BUSINESS_UNIT" LIKE 'IF%')                                                                                                                                                                                                                                                                
           filter("B"."BUSINESS_UNIT" LIKE 'IF%')                                                                                                                                                                                                                                                                
      20 - filter("A"."RECV_STATUS"<>'C' AND "A"."BUSINESS_UNIT" LIKE 'IF%')                                                                                                                                                                                                                                     
      23 - access("C"."BUSINESS_UNIT"=:B1 AND "C"."LANGUAGE_CD"='FRA')                                                                                                                                                                                                                                           
      24 - access("B"."BUSINESS_UNIT"=:B1)                                                                                                                                                                                                                                                                       
           filter("B"."BUSINESS_UNIT"="C"."BUSINESS_UNIT")                                                                                                                                                                                                                                                       
      25 - access("A"."BUSINESS_UNIT"="B"."BUSINESS_UNIT")                                                                                                                                                                                                                                                       
           filter("A"."RECV_STATUS"<>'C' AND "A"."BUSINESS_UNIT"=:B1)                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                 
    Note                                                                                                                                                                                                                                                                                                         
    -----                                                                                                                                                                                                                                                                                                        
       - 'PLAN_TABLE' is old version                                                                                                                                                                                                                                                                             
    
    65 rows selected
    
    1 273 ms écoulées
    
    ==============================================================================================
    SQL> select sid, osuser,row_wait_obj#,program,event from v$session where program like '%Dev%' and osuser='myuser';
    
           SID OSUSER          ROW_WAIT_OBJ# PROGRAM         EVENT
    ---------- --------------- ------------- --------------- ---------------
            29 myuser                51715 SQL Developer   SQL*Net message
                                                              from client
    
    SQL> select  object_type, object_name, data_object_id
      2  from dba_objects
      3  where object_id = 51715;
    
    OBJECT_TYPE         OBJECT_NAME     DATA_OBJECT_ID
    ------------------- --------------- --------------
    INDEX               PSCRECV_HDR              51715
    Thank you.

    Are accurate statistics, the query returns about 10 billion lines, and if so how long you expect to take?
    Can send you a SQL trace with details of actual file?

  • The index used is not in the group by.

    Here's the scenario with examples. The big table 333 to 500 million in the table rows. Statistics are collected. Are there histograms. Index is not however be used. Why?
      CREATE TABLE "XXFOCUS"."some_huge_data_table" 
       (  "ORG_ID" NUMBER NOT NULL ENABLE, 
      "PARTNERID" VARCHAR2(30) NOT NULL ENABLE, 
      "EDI_END_DATE" DATE NOT NULL ENABLE, 
      "CUSTOMER_ITEM_NUMBER" VARCHAR2(50) NOT NULL ENABLE, 
      "STORE_NUMBER" VARCHAR2(10) NOT NULL ENABLE, 
      "EDI_START_DATE" DATE, 
      "QTY_SOLD_UNIT" NUMBER(7,0), 
      "QTY_ON_ORDER_UNIT" NUMBER(7,0), 
      "QTY_ON_ORDER_AMT" NUMBER(10,2), 
      "QTY_ON_HAND_AMT" NUMBER(10,2), 
      "QTY_ON_HAND_UNIT" NUMBER(7,0), 
      "QTY_SOLD_AMT" NUMBER(10,2), 
      "QTY_RECEIVED_UNIT" NUMBER(7,0), 
      "QTY_RECEIVED_AMT" NUMBER(10,2), 
      "QTY_REQUISITION_RDC_UNIT" NUMBER(7,0), 
         "QTY_REQUISITION_RDC_AMT" NUMBER(10,2), 
         "QTY_REQUISITION_RCVD_UNIT" NUMBER(7,0), 
         "QTY_REQUISITION_RCVD_AMT" NUMBER(10,2), 
         "INSERTED_DATE" DATE, 
         "UPDATED_DATE" DATE, 
         "CUSTOMER_WEEK" NUMBER, 
         "CUSTOMER_MONTH" NUMBER, 
         "CUSTOMER_QUARTER" NUMBER, 
         "CUSTOMER_YEAR" NUMBER, 
         "CUSTOMER_ID" NUMBER, 
         "MONTH_NAME" VARCHAR2(3), 
         "ORG_WEEK" NUMBER, 
         "ORG_MONTH" NUMBER, 
         "ORG_QUARTER" NUMBER, 
         "ORG_YEAR" NUMBER, 
         "SITE_ID" NUMBER, 
         "ITEM_ID" NUMBER, 
         "ITEM_COST" NUMBER, 
         "UNIT_PRICE" NUMBER, 
          CONSTRAINT "some_huge_data_table_PK" PRIMARY KEY ("ORG_ID", "PARTNERID", "EDI_END_DATE", "CUSTOMER_ITEM_NUMBER", "STORE_NUMBER")
      USING INDEX TABLESPACE "xxxxx"  ENABLE, 
          CONSTRAINT "some_huge_data_table_CK_START_DATE" CHECK (edi_end_date - edi_start_date = 6) ENABLE
       );
    
    SQL*Plus: Release 11.2.0.2.0 Production on Fri Sep 14 12:11:16 2012
    
    Copyright (c) 1982, 2010, Oracle.  All rights reserved.
    
    
    Connected to:
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options
    
    SQL> SELECT num_rows FROM user_tables s WHERE s.table_name = 'some_huge_data_table';
    
      NUM_ROWS                                                                      
    ----------                                                                      
     333338434                                                                      
    
    SQL> SELECT MAX(edi_end_date)
      2    FROM some_huge_data_table p
      3   WHERE p.org_id = some_number
      4     AND p.partnerid = 'some_string';
    
    MAX(EDI_E                                                                       
    ---------                                                                       
    13-MAY-12                                                                       
    
    Elapsed: 00:00:00.00
    
    
    SQL> explain plan for
      2  SELECT MAX(edi_end_date)
      3    FROM some_huge_data_table p
      4   WHERE p.org_id = some_number
      5     AND p.partnerid = 'some_string';
    
    Explained.
    
    SQL> /
    
    PLAN_TABLE_OUTPUT                                                                                   
    ----------------------------------------------------------------------------------------------------
    Plan hash value: 2104157595                                                                         
                                                                                                        
    --------------------------------------------------------------------------------------------        
    | Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |        
    --------------------------------------------------------------------------------------------        
    |   0 | SELECT STATEMENT             |             |     1 |    22 |     4   (0)| 00:00:01 |        
    |   1 |  SORT AGGREGATE              |             |     1 |    22 |            |          |        
    |   2 |   FIRST ROW                  |             |     1 |    22 |     4   (0)| 00:00:01 |        
    |*  3 |    INDEX RANGE SCAN (MIN/MAX)| some_huge_data_table_PK |     1 |    22 |     4   (0)| 00:00:01 |        
    --------------------------------------------------------------------------------------------        
    
    SQL> explain plan for
      2  SELECT MAX(edi_end_date),
      3         org_id,
      4         partnerid
      5    FROM some_huge_data_table
      6   GROUP BY org_id,
      7            partnerid;
    
    Explained.
    
    PLAN_TABLE_OUTPUT                                                                                   
    ----------------------------------------------------------------------------------------------------
    Plan hash value: 3950336305                                                                         
                                                                                                        
    -------------------------------------------------------------------------------                     
    | Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     |                     
    -------------------------------------------------------------------------------                     
    |   0 | SELECT STATEMENT   |          |     2 |    44 |  1605K  (1)| 05:21:03 |                     
    |   1 |  HASH GROUP BY     |          |     2 |    44 |  1605K  (1)| 05:21:03 |                     
    |   2 |   TABLE ACCESS FULL| some_huge_data_table |   333M|  6993M|  1592K  (1)| 05:18:33 |                     
    -------------------------------------------------------------------------------                     
    Why is he would not use the index in the group by? If I write a loop to search for different partnerid (there are only three), things together takes less than a second. Any help is appreciated.

    BTW, I too gave the index indicator. Did not work. Version mentioned in the example.

    Published by: RPuttagunta on September 14, 2012 11:24

    Published by: RPuttagunta on September 14, 2012 11:26

    the actual names are 'cleaned' for obvious reasons. Don't worry, I don't have the name of the tables in different cases.

    RPuttagunta wrote:

    Looks like either I called index_ss asked Jonathan a bad indicator, or, I don't know if he used the 'skip scan ".

    You don't specify correctly, it should be: index_ss (table_alias) or index_ss (table_alias index_name) or index_ss (table_alias (list of columns to index)).

    But I just tried a quick test on 11.2.0.3, and he does not have what we would really like to do.

    Concerning
    Jonathan Lewis

  • How oracle decide whetehr to use the index or full analysis (statistics)

    Hi guys,.

    Let's say I have an index on a column.
    Tables and index statistics were collected. (without the histograms).

    Let's say I have run a select * from table where a = 5;
    Oracle will perform a complete analysis.
    But what statistics, it will be able to know indeed the greater part of the column = 5? (histograms do not used)

    After analysis, we get the following:
    Statistical table:
    (NUM_ROWS)
    (BLOCKS)
    (EMPTY_BLOCKS)
    (AVG_SPACE)
    (CHAIN_COUNT)
    (AVG_ROW_LEN)

    Index statistics:
    (BLEVEL)
    (LEAF_BLOCKS)
    (DISTINCT_KEYS)
    (AVG_LEAF_BLOCKS_PER_KEY)
    (AVG_DATA_BLOCKS_PER_KEY)
    (CLUSTERING_FACTOR)

    Thank you





    Index of column (A)
    ======
    1
    1
    2
    2
    5
    5
    5
    5
    5
    5

    I have prepared a few explanations and did not notice that the topic has been marked as answer.

    My sentence is not quite true.

    A column "without histograms' means that the column has only a bucket.

    More correct: even without the histogram there are data in dba_tab_histograms which can be considered a bucket for the whole column. In fact, these data are extracted from hist_head$, not from $ histgrm as usual buckets.
    Technically there are no buckets without combined histograms.

    Let's create a table with the asymmetric data distribution.

    SQL> create table t as
      2  select least(rownum,3) as val, '*' as pad
      3    from dual
      4  connect by level <= 1000000;
    
    Table created
    
    SQL> create index idx on t(val);
    
    Index created
    
    SQL> select val, count(*)
      2    from t
      3   group by val;
    
           VAL   COUNT(*)
    ---------- ----------
             1          1
             2          1
             3     999998
    

    So, we have table with the very uneven distribution of the data.
    We collect statistics without histograms.

    SQL> exec dbms_stats.gather_table_stats( user, 'T', estimate_percent => 100, method_opt => 'for all columns size 1', cascade => true);
    
    PL/SQL procedure successfully completed
    
    SQL> select blocks, num_rows  from dba_tab_statistics
      2   where table_name = 'T';
    
        BLOCKS   NUM_ROWS
    ---------- ----------
          3106    1000000
    
    SQL> select blevel, leaf_blocks, clustering_factor
      2    from dba_ind_statistics t
      3   where table_name = 'T'
      4     and index_name = 'IDX';
    
        BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR
    ---------- ----------- -----------------
             2        4017              3107
    
    SQL> select column_name,
      2         num_distinct,
      3         density,
      4         num_nulls,
      5         low_value,
      6         high_value
      7    from dba_tab_col_statistics
      8   where table_name = 'T'
      9     and column_name = 'VAL';
    
    COLUMN_NAME  NUM_DISTINCT    DENSITY  NUM_NULLS      LOW_VALUE      HIGH_VALUE
    ------------ ------------ ---------- ---------- -------------- ---------------
    VAL                     3 0,33333333          0           C102            C104
    

    Therefore, Oracle suggests that the values between 1 and 3 (raw C102 C104) are distributed uniform and the density of the distribution is 0.33.
    We will try to explain the plan

    SQL> explain plan for
      2  select --+ no_cpu_costing
      3         *
      4    from t
      5   where val = 1
      6  ;
    
    Explained
    
    SQL> @plan
    
    --------------------------------------------------
    | Id  | Operation         | Name | Rows  | Cost  |
    --------------------------------------------------
    |   0 | SELECT STATEMENT  |      |   333K|   300 |
    |*  1 |  TABLE ACCESS FULL| T    |   333K|   300 |
    --------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       1 - filter("VAL"=1)
    Note
    -----
       - cpu costing is off (consider enabling it)
    

    An excerpt from trace 10053

    BASE STATISTICAL INFORMATION
    ***********************
    Table Stats::
      Table:  T  Alias:  T
        #Rows: 1000000  #Blks:  3106  AvgRowLen:  5.00
    Index Stats::
      Index: IDX  Col#: 1
        LVLS: 2  #LB: 4017  #DK: 3  LB/K: 1339.00  DB/K: 1035.00  CLUF: 3107.00
    ***************************************
    SINGLE TABLE ACCESS PATH
      -----------------------------------------
      BEGIN Single Table Cardinality Estimation
      -----------------------------------------
      Column (#1): VAL(NUMBER)
        AvgLen: 3.00 NDV: 3 Nulls: 0 Density: 0.33333 Min: 1 Max: 3
      Table:  T  Alias: T
        Card: Original: 1000000  Rounded: 333333  Computed: 333333.33  Non Adjusted: 333333.33
      -----------------------------------------
      END   Single Table Cardinality Estimation
      -----------------------------------------
      Access Path: TableScan
        Cost:  300.00  Resp: 300.00  Degree: 0
          Cost_io: 300.00  Cost_cpu: 0
          Resp_io: 300.00  Resp_cpu: 0
      Access Path: index (AllEqRange)
        Index: IDX
        resc_io: 2377.00  resc_cpu: 0
        ix_sel: 0.33333  ix_sel_with_filters: 0.33333
        Cost: 2377.00  Resp: 2377.00  Degree: 1
      Best:: AccessPath: TableScan
             Cost: 300.00  Degree: 1  Resp: 300.00  Card: 333333.33  Bytes: 0
    

    FTS here costs 300 and Index Range Scan here costs 2377.
    I disabled cpu cost, so the selectivity does not affect the cost of FTS.
    cost of the Index Range Scan is calculated as
    blevel + (leaf_blocks * selectivity + clustering_factor * selecivity) = 2 + (4017 * 0.33333 + 3107 * 0.33333) = 2377.
    Oracle believes that he must read 2 blocks root/branch index, 1339 the index leaf blocks and 1036 blocks in the table.
    Pay attention that the selectivity is the main component of the cost of the Index Range Scan.

    We will try to collect histograms:

    SQL> exec dbms_stats.gather_table_stats( user, 'T', estimate_percent => 100, method_opt => 'for columns val size 3', cascade => true);
    
    PL/SQL procedure successfully completed
    

    If you look at dba_tab_histograms you can see more

    SQL> select endpoint_value,
      2         endpoint_number
      3    from dba_tab_histograms
      4   where table_name = 'T'
      5     and column_name = 'VAL'
      6  ;
    
    ENDPOINT_VALUE ENDPOINT_NUMBER
    -------------- ---------------
                 1               1
                 2               2
                 3         1000000
    

    ENDPOINT_VALUE is the value of the column (in number for any type of data) and ENDPOINT_NUMBER is the cumulative number of lines.
    Number of lines for any ENDPOINT_VALUE = ENDPOINT_NUMBER for this ENDPOINT_VALUE - ENDPOINT_NUMBER to the previous ENDPOINT_VALUE.

    explain the plan and track 10053 the same query:

    ------------------------------------------------------------
    | Id  | Operation                   | Name | Rows  | Cost  |
    ------------------------------------------------------------
    |   0 | SELECT STATEMENT            |      |     1 |     4 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| T    |     1 |     4 |
    |*  2 |   INDEX RANGE SCAN          | IDX  |     1 |     3 |
    ------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       2 - access("VAL"=1)
    Note
    -----
       - cpu costing is off (consider enabling it)
    
    ***************************************
    BASE STATISTICAL INFORMATION
    ***********************
    Table Stats::
      Table:  T  Alias:  T
        #Rows: 1000000  #Blks:  3106  AvgRowLen:  5.00
    Index Stats::
      Index: IDX  Col#: 1
        LVLS: 2  #LB: 4017  #DK: 3  LB/K: 1339.00  DB/K: 1035.00  CLUF: 3107.00
    ***************************************
    SINGLE TABLE ACCESS PATH
      -----------------------------------------
      BEGIN Single Table Cardinality Estimation
      -----------------------------------------
      Column (#1): VAL(NUMBER)
        AvgLen: 3.00 NDV: 3 Nulls: 0 Density: 5.0000e-07 Min: 1 Max: 3
        Histogram: Freq  #Bkts: 3  UncompBkts: 1000000  EndPtVals: 3
      Table:  T  Alias: T
        Card: Original: 1000000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
      -----------------------------------------
      END   Single Table Cardinality Estimation
      -----------------------------------------
      Access Path: TableScan
        Cost:  300.00  Resp: 300.00  Degree: 0
          Cost_io: 300.00  Cost_cpu: 0
          Resp_io: 300.00  Resp_cpu: 0
      Access Path: index (AllEqRange)
        Index: IDX
        resc_io: 4.00  resc_cpu: 0
        ix_sel: 1.0000e-06  ix_sel_with_filters: 1.0000e-06
        Cost: 4.00  Resp: 4.00  Degree: 1
      Best:: AccessPath: IndexRange  Index: IDX
             Cost: 4.00  Degree: 1  Resp: 4.00  Card: 1.00  Bytes: 0
    

    Be careful on selectivity, ix_sel: 1.0000e - 06
    Cost of the FTS is always the same = 300,
    but the cost of the Index Range Scan is now 4: 2 blocks from root/branch + block 1 sheet + 1 table blocks.

    So, conclusion: histograms to calculate more accurate selectivity. The goal is to have more efficient execution plans.

    Alexander Anokhin
    http://alexanderanokhin.WordPress.com/

  • SELECT on a table in the INSERT statement uses the INDEX

    Hello world

    I have a strange problem with EA Oracle 10 g (64-bit) running on a Linux system. The situation is, I developed a Java program to migrate one client system to another. One of the steps in the migration fills a new table with the data from the old system. Given that the data on the old system structure is fundamentally different from that new, I have to check each time I read a line from the old system, if I have already created an entity on the new table, and if so, update certain attributes. The WHERE clause of this audit uses a key of the company indexed on the new table. The problem is now, that Oracle does not use the index on the key attribute of the company, but it makes table scans complete to select the line. As you can imagine, the lines first thousand or so go fast, but the amount increases, the program becomes slower and slower.

    If I do a "scan" when executing the migration program, Oracle change the execution plan and use the index on the attribute key and everything works fast and smooth. However, if I do the analysis on the empty table first, nothing changes (which I understand it perfectly, since there is nothing to analyze, at this point). By integrating a hint of 'INDEX' (table) in the statement SELECT does not change the full implementation plan (also table scans).

    Is it possible to change this behavior, in order to SELECT it uses the index of key business from the beginning?

    Greetings from Cologne,

    Thorsten.

    Published by: thkitz on 13.03.2012 18:27

    thkitz wrote:

    SELECT STATEMENT  ALL_ROWSCost: 2  Bytes: 76  Cardinality: 2
         7 TABLE ACCESS BY INDEX ROWID TABLE AIDATINT.PRVVSSCHADENKORRESPONDENZ Cost: 2  Bytes: 76  Cardinality: 2
              6 BITMAP CONVERSION TO ROWIDS
                   5 BITMAP OR
                        2 BITMAP CONVERSION FROM ROWIDS
                             1 INDEX RANGE SCAN INDEX AIDATINT.I_PRVVSSCHADENKORRESPONDENZ_1 Cost: 1
                        4 BITMAP CONVERSION FROM ROWIDS
                             3 INDEX RANGE SCAN INDEX AIDATINT.I_PRVVSSCHADENKORRESPONDENZ_2 Cost: 1  
    

    I would have thought that as a plan as possible. It is not a concatenation, is a btree/bitmap conversion.
    Allude to this plan you need / * + index_combine (table_alias index1 index2) * /.
    For 10g and later the index can be specified by name or by description

    I'm a bit puzzled why the plan changes after truncate - but maybe my comment about not cleared statistics is no longer true. It is easy enough to check if I'm right or wrong on your version of Oracle.

    Concerning
    Jonathan Lewis
    http://jonathanlewis.WordPress.com
    Author: core Oracle

  • CBO promotes the basic function of the index (descending)

    Location:

    Table 1 million records, 1 GB in size

    Multiple indexes, including an index on three columns, one of these DESC


    A particular query uses this index and made coherent 40,000 gets to return 1635 records.

    The plan
    ------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |            |    75 |  1275 |     3   (0)| 00:00:01 |
    |*  1 |  INDEX RANGE SCAN DESCENDING| IHISTOJOUR |    75 |  1275 |     3   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------
    I have a second index on the same columns (in a different order) that much better appearss adapted to education.
    When forcing this index with a hint, the uniform becomes fall to as little as 16 for the same set of results
    ------------------------------------------------------------------------------------
    | Id  | Operation        | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |                 |    75 |  1275 |     4   (0)| 00:00:01 |
    |*  1 |  INDEX RANGE SCAN| IHISTOJOUR2     |    75 |  1275 |     4   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------
    The statistics have been freshly calculated (for all columns size skewonly)
    Version Oracle 11.2.0.1


    I can't understand why Oracle choose the order of the function based on the normal index, however.


    Any thoughts?

    This is one of those cases where through a 10053 is probably appropriate.

    In my 10053 trace, I found this line:

    Using prorated density: 0.000000 of col #4 as selectvity of
    out-of-range/non-existent value pred
    

    COL #4 corresponding to the virtual column for the descending column in the index.

    There are a couple of notes on metalink about 'sub-optimal index is used when the index column is in descending order' and a number of bug - 11072246 - confirmed as affecting > = 10.2.0.5 and<=>

    In the notes for this bug, this seems relevant:
    "Selectivity of the Index has been calculated is not properly considering the DESC property.

    By the way, another possible oddity was that, even if I've calculated the statistics with the size of the sample of 100% and it checked with sample_size in dba_tab_col_statistics, the LO_VAL of DAT and the virtual column never matched.
    Convert the raw, DAT was a lo_val of 2 January 2001 and a hi_val 27-SEP-2003.
    While the virtual columns had 8 January 2001 and 27-SEP-2003. difference of 6 days. Weird, right?

    Published by: Dom Brooks on November 10, 2011 17:18

Maybe you are looking for