Function Based Index And Selectivity

Hi All,
I have some doubts w.r.t FBI.I am on 10gR2 (10.2.0.4) with Solaris 5.9
I was under impression that FBI does not provide guaranteed index access and CBO choose access pattern purely on basis of available stats and query selectivity.
However, many a times i found that CBO is going for FBI even in case when FTS provides better query elapsed time.
I created following test case:
create table fbi_test (id number,flag varchar2(1));
begin
for i in 1..1000000
loop
insert into fbi_test values(i,'Y');
end loop;
end;
commit;
begin
for i in 1..10
loop
insert into fbi_test values(i,'N');
end loop;
end;
commit;
ANALYZE TABLE FBI_TEST COMPUTE STATISTICS;
CREATE INDEX fbi_test_FBI
ON fbi_test (CASE WHEN flag = 'Y' THEN 1 ELSE NULL END);
Autotrace for FBI ACCESS
SQL> select *from fbi_test where (CASE WHEN flag = 'Y' THEN 1 ELSE NULL END)=1;
1000000 rows selected.
Elapsed: 00:00:18.43
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 10000 | 50000 | 342 (1)|
| 1 | TABLE ACCESS BY INDEX ROWID| FBI_TEST | 10000 | 50000 | 342 (1)|
|* 2 | INDEX RANGE SCAN | FBI_TEST_FBI | 4000 | | 1958 (1)|
Statistics
0 recursive calls
0 db block gets
136812 consistent gets
0 physical reads
0 redo size
22180292 bytes sent via SQL*Net to client
733814 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000000 rows processed
Autotrace for FTS
SQL> select *from fbi_test where flag = 'Y';
1000000 rows selected.
Elapsed: 00:00:16.56
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 500K| 2441K| 371 (9)|
|* 1 | TABLE ACCESS FULL| FBI_TEST | 500K| 2441K| 371 (9)|
Statistics
0 recursive calls
0 db block gets
68372 consistent gets
0 physical reads
0 redo size
22180292 bytes sent via SQL*Net to client
733814 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000000 rows processed
FYI...
SQL> show parameter opt
NAME TYPE VALUE
filesystemio_options string asynch
object_cache_optimal_size integer 102400
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.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
plsql_optimize_level integer 2
My questions are,
1.why oracle optimizer is going for FBI with high cardinality of 100000 rows?
2.Why cost of FTS is high (371) as compare to FBI (342) eventhough FTS is having fewer IO (68372) + Less Elapsed Time?
3.Why Optimizer is considering ELAPSED TIME during plan generation?
Any inpute would be highly appreciated.

user635930 wrote:
Hi All,
I have some doubts w.r.t FBI.I am on 10gR2 (10.2.0.4) with Solaris 5.9
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 10000 | 50000 | 342 (1)|
| 1 | TABLE ACCESS BY INDEX ROWID| FBI_TEST | 10000 | 50000 | 342 (1)|
|* 2 | INDEX RANGE SCAN | FBI_TEST_FBI | 4000 | | 1958 (1)|
---------------------------------------------------------------------------------You're seeing three different effects here.
First - for the table access by index, Oracle has "lost" the cost of the index range scan - notice that the total cost of the query is 342, but the cost of the index access is 1958. The total cost of the query should be 2,300 and Oracle should have chosen the full tablescan automatically.
Second, the stats on the index show just one distinct value for "distinct_keys", and the optimizer has decided (for no reason I can think of - it may be a bug) to assume a 0.4% selectivity on the index.
Third, the estimated cardinality of the table and index lines differs. Whatever Oracle has done in the index line has been forgotten, and the cardinality of the table line has been based on the predicate given by your case statement and, as a "complex function", that predicate has been given a selectivity of 1% - hence the 10,000 rows estimate.
The combination of unsuitable statistics, an extreme case, and a couple of quirks in the optimizer mean that the chosen path is clearly unsuitable.
[Addendum]: It just occurred to me that part of the problem is that you collected stats on the table before you created the index. Given you're running 10g, the 'create index' would automatically generate index stats at the same time - but since it's a function-based index, there's a "virtual column" created for the table as well, and that column won't have any statistics on it - which is why you get the "fixed percentage" selectivities.
Regards
Jonathan Lewis
http://jonathanlewis.wordpress.com
http://www.jlcomp.demon.co.uk
"Science is more than a body of knowledge; it is a way of thinking" Carl Sagan
Edited by: Jonathan Lewis on Nov 29, 2008 1:15 PM

Similar Messages

  • Differences between function based index and normal index

    Hi,
    Please Give me some differences between function based index and normal indexes.
    1. Is there any performance gain in function based index?
    2. Why indexes created in DESC are treated as function based?
    3. Every DESC index is b-tree index?
    Thanks

    check this link. This would give u a basic idea of what a function based index is .
    http://www.oracle-base.com/articles/8i/FunctionBasedIndexes.php
    --Prasad                                                                                                                                                                                                                                                                                                                                       

  • Function-based Index and an OR-condition in the WHERE-clause

    We have some problems with functin-based indexes and
    the or-condition in a where-clause.
    (We use oracle 8i (8.1.7))
    create table TPERSON(ID number(10),NAME varchar2(20),...);
    create index I_NORMAL_TPERSON_NAME on TPERSON(NAME);
    create index I_FUNCTION_TPERSON_NAME on TPERSON(UPPER(NAME));
    The following two statements run very fast on a large table
    and the execution-plan asure the usage of the indexes
    (-while the session is appropriate configured and the table is analyzed):
    1)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%';
    2)     select count(ID) from TPERSON where NAME like 'Mil%' or (3=5);
    In particular we see that a normal index is used while the where-clause contains
    an OR-CONDITION.
    But if we try the similarly select-statement
    3)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%' or (3=5);
    the CBO will not use the function-index.
    (This behavior we only expect with views but not with indexes.)
    We ask for an advice like an hint, which enable the CBO-usage
    of function-based indexes in connection with OR.
    This problem seems to be artificial because it contains this dummy logic:
         or (3=5).
    This steams from an prepared statement, where this kind of boolean
    flag reduce the amount of different select-statements needed for
    covering the hole business-logic, while using bind-variables for the
    concrete query-parameters.
    A more realistic (still boild down) version of our prepared select-statement run in
    SQL Plus:
    define x_name = 'MIL%';
    define x_firstname = '';
    select * FROM TPERSON
    where (upper(NAME) like '&x_name' or ( '&x_name' = ''))
    and (upper(FIRSTNAME) like '&x_firstname' or ('&x_firstname' = ''))
    and ...;
    In particular we dont refernce the tablecolumn , but the QUERY-Parameter
    yield the second boolean value in the or-condition.
    The problem is that this condition ('&x_name' = '') dont use any index.
    thanks a lot for spending your time with this problem

    Try
    SELECT /*+ RULE */
    as your hint. I don't have the book with me, but this last weekend I read a section about your very problem. The book was a Oracle Press gold cover about Oracle 8i Performance tuning. If you e-mail me I can quote you the chapter when I get home Friday.

  • Function based Indexes and user_tab_cols

    Why an entry is created in user_tab_cols when we create a function based on a column of a table?
    create table t1(a varchar2(100), b number); 
    select * from user_tab_cols where table_name = 'T1'; -- Two rows coming 
    create index idx1 on t1(upper(a));
    select * from user_tab_cols where table_name = 'T1'; -- Three rows coming
    What is the reason to put an entry in user_tab_cols?

    Hi,
    Martin Preiss wrote:
    if my memory serves me well there is also an attribute VIRTUAL_COLUMN in %_TAB_COLS (at least since 11.1).
    This is interesting!
    In Oracle 11.2.0.2.0, when logged in as a developer with limited privileges, I don't see that column when using DESCRIBE:
    SQL> desc user_tab_columns
    Name                                      Null?    Type
    TABLE_NAME                                NOT NULL VARCHAR2(30)
    COLUMN_NAME                               NOT NULL VARCHAR2(30)
    DATA_TYPE                                          VARCHAR2(106)
    DATA_TYPE_MOD                                      VARCHAR2(3)
    DATA_TYPE_OWNER                                    VARCHAR2(120)
    DATA_LENGTH                               NOT NULL NUMBER
    DATA_PRECISION                                     NUMBER
    DATA_SCALE                                         NUMBER
    NULLABLE                                           VARCHAR2(1)
    COLUMN_ID                                          NUMBER
    DEFAULT_LENGTH                                     NUMBER
    DATA_DEFAULT                                       LONG
    NUM_DISTINCT                                       NUMBER
    LOW_VALUE                                          RAW(32)
    HIGH_VALUE                                         RAW(32)
    DENSITY                                            NUMBER
    NUM_NULLS                                          NUMBER
    NUM_BUCKETS                                        NUMBER
    LAST_ANALYZED                                      DATE
    SAMPLE_SIZE                                        NUMBER
    CHARACTER_SET_NAME                                 VARCHAR2(44)
    CHAR_COL_DECL_LENGTH                               NUMBER
    GLOBAL_STATS                                       VARCHAR2(3)
    USER_STATS                                         VARCHAR2(3)
    AVG_COL_LEN                                        NUMBER
    CHAR_LENGTH                                        NUMBER
    CHAR_USED                                          VARCHAR2(1)
    V80_FMT_IMAGE                                      VARCHAR2(3)
    DATA_UPGRADED                                      VARCHAR2(3)
    HISTOGRAM                                          VARCHAR2(15)
    But when logged in as SYSTEM on the same database, I do see it:
    SQL> DESC USER_TAB_COLS
    Name                                      Null?    Type
    TABLE_NAME                                NOT NULL VARCHAR2(30)
    COLUMN_NAME                               NOT NULL VARCHAR2(30)
    DATA_TYPE                                          VARCHAR2(106)
    DATA_TYPE_MOD                                      VARCHAR2(3)
    DATA_TYPE_OWNER                                    VARCHAR2(120)
    DATA_LENGTH                               NOT NULL NUMBER
    DATA_PRECISION                                     NUMBER
    DATA_SCALE                                         NUMBER
    NULLABLE                                           VARCHAR2(1)
    COLUMN_ID                                          NUMBER
    DEFAULT_LENGTH                                     NUMBER
    DATA_DEFAULT                                       LONG
    NUM_DISTINCT                                       NUMBER
    LOW_VALUE                                          RAW(32)
    HIGH_VALUE                                         RAW(32)
    DENSITY                                            NUMBER
    NUM_NULLS                                          NUMBER
    NUM_BUCKETS                                        NUMBER
    LAST_ANALYZED                                      DATE
    SAMPLE_SIZE                                        NUMBER
    CHARACTER_SET_NAME                                 VARCHAR2(44)
    CHAR_COL_DECL_LENGTH                               NUMBER
    GLOBAL_STATS                                       VARCHAR2(3)
    USER_STATS                                         VARCHAR2(3)
    AVG_COL_LEN                                        NUMBER
    CHAR_LENGTH                                        NUMBER
    CHAR_USED                                          VARCHAR2(1)
    V80_FMT_IMAGE                                      VARCHAR2(3)
    DATA_UPGRADED                                      VARCHAR2(3)
    HIDDEN_COLUMN                                      VARCHAR2(3)
    VIRTUAL_COLUMN                                     VARCHAR2(3)
    SEGMENT_COLUMN_ID                                  NUMBER
    INTERNAL_COLUMN_ID                        NOT NULL NUMBER
    HISTOGRAM                                          VARCHAR2(15)
    QUALIFIED_COL_NAME                                 VARCHAR2(4000)
    I can see that column in ALL_TAB_COLS either way.

  • Function Based Index and ORA-01450

    The following DDL produces ORA-01450 (maximum key length (758) exceeded) :
    create index test_fn_ix1 on ausv_int_acc (test_package.test_function(intacc_username));
    Here's the package :
    create or replace package test_package
    is
    function test_function (value_in varchar2) return varchar2 deterministic;
    end test_package;
    create or replace package body test_package
    is
    function test_function (value_in varchar2) return varchar2
    is
    begin
    return ''| |value_in;
    end test_function;
    end test_package;
    Obviously this is only a test function but I have a real function I want to use - I have just tried to simplify the problem.
    How does Oracle know how long the function result is ? - it doesn't because you can't specify return length of a function, just the type !
    I have got round this problem thus :
    create index test_fn_ix1 on ausv_int_acc (substr(test_package.test_function(intacc_username),1,100));
    Surly there's a tidier way ???
    Thanks for any help
    Angus

    Hi,
    You can add SUBSTRs, like this:
    CREATE UNIQUE INDEX addresses_uq1
           ON addresses ( UPPER( SUBSTR (REGEXP_REPLACE( STREET1,'([^[:alnum:]])',''), 1, 50) ),
                          UPPER( SUBSTR (REGEXP_REPLACE( STREET2,'([^[:alnum:]])',''), 1, 50) ),
                          UPPER( SUBSTR (REGEXP_REPLACE( CITY,   '([^[:alpha:]])',''), 1, 50) ),
                          COUNTRY_CODE,
                          STATE_CODE );Why?
    Try this:
    CREATE OR REPLACE VIEW  view_x
    AS
    SELECT  UPPER( REGEXP_REPLACE( STREET1,'([^[:alnum:]])','') )     AS street1
    FROM     addresses;
    DESC     view_xYou'll see that view_x.street1 is VARCHAR2 *(4000)* .
    You and I know that the REGEXP_REPLACE function is taking a 50-character (max) string, and, if anything, reducing its size. But the system doesn't figure out what REGEXP_REPLACE is doing; for all it knows, REGEXP_REPLACE could be returning any VARCHAR2, so it allows room for the biggest possible VARCHAR2.

  • Function based indexes on object tables

    Hi,
    I am trying to create a function based index on an object table. I am getting the following error:
    SQL> create index cell1_indx on cell1(create_cell1(id)) indextype is mdsys.spatial_index;
    create index cell1_indx on cell1(create_cell1(id)) indextype is mdsys.spatial_index
    ERROR at line 1:
    ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
    ORA-13249: internal error in Spatial index: [mdidxrbd]
    ORA-13249: Error in Spatial index: index build failed
    ORA-13249: Stmt-Execute Failure: SELECT num_rows from all_tables where owner='ASHE' and table_name=
    'CELL1'
    ORA-06512: at "MDSYS.SDO_INDEX_METHOD_9I", line 7
    ORA-06512: at line 1
    Here cell1 is an object table.
    Is the procedure for creating function based indexes on object tables different from relational tables?
    Chinni

    One of the many new features in Oracle 8i is the Function-Based Index (we will refrain from using FBI, but only just). This allows the DBA to create indexes on functions or expressions; these functions can be user generated pl/sql functions, standard SQL functions (non-aggregate only) or even a C callout.
    A classic problem the DBA faces in SQL Tuning is how to tune those queries that use function calls in the where clause, and result in indexes created on these columns not to be used.
    Example
    Standard B-Tree index on SURNAME with cost based optimizer
    create index non_fbi on sale_contacts (surname);
    analyze index non_fbi compute statistics;
    analyze table sale_contacts compute statistics;
    SELECT count(*) FROM sale_contacts
    WHERE UPPER(surname) = 'ELLISON';
    Execution Plan
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=17)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF 'SALES_CONTACTS' (Cost=3 Card=16 Bytes=272)
    Now we use a function based index
    create index fbi on sale_contacts (UPPER(surname));
    analyze index fbi compute statistics;
    analyze table sale_contacts compute statistics;
    SELECT count(*) FROM sale_contacts WHERE UPPER(surname) = 'ELLISON';
    Execution Plan
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=17)
    1 0 SORT (AGGREGATE)
    2 1 INDEX (RANGE SCAN) OF 'FBI' (NON-UNIQUE) (Cost=2 Card=381 Bytes=6477)
    The function-based index has forced the optimizer to use index range scans (retuning zero or more rowids) on the surname column rather than doing a full table scan (non-index lookup). Optimal performance does vary depending on table size, uniqueness and selectivity of columns, use of fast full table scans etc. Therefore try both methods to gain optimal performance in your database.
    It is important to remember that the function-based B*Tree index does not store the expression results in the index but uses an "expression tree". The optimizer performs expression matching by parsing the expression used in the SQL statement and comparing the results against the expression-tree values in the function-based index. This comparison IS case sensitive (ignores spaces) and therefore your function-based index expressions should match expressions used in the SQL statement where clauses.
    Init.ora Parameters
    The following parameter must be set in your parameter file: QUERY_REWRITE_INTEGRITY = TRUSTED
    QUERY_REWRITE_ENABLED = TRUE
    COMPATIBLE = 8.1.0.0.0 (or higher)
    Grants
    Grants To create function-based indexes the user must be granted CREATE INDEX and QUERY REWRITE, or alternatively be granted CREATE ANY INDEX and GLOBAL QUERY REWRITE. The index owner must have EXECUTE access on the function used for the index. If execute access is revoked then the function-based index will be "disabled" (see dba_indexes).
    Disabled Indexes
    If your function-based index has a status of "disabled" the DBA can do one of the following:
    a) drop and create the index (take note of its current settings)
    b) alter index enable, function-based indexes only, also use disable keyword as required
    c) alter index unusable.
    Queries on a DISABLED index fail if the optimizer chooses to use the index.Here is an example ORA error:
    ERROR at line 1: ORA-30554: function-based index MYUSER.FBI is disabled.
    All DML operations on a DISABLED index also fail unless the index is also marked UNUSABLE and the initialization parameter SKIP_UNUSABLE_INDEXES is set to true.
    Some more Examples
    CREATE INDEX expression_ndx
    ON mytable ((mycola + mycolc) * mycolb);
    SELECT mycolc FROM mytable
    WHERE (mycola + mycolc) * mycolb <= 256;
    ..or a composite index..
    CREATE INDEX example_ndx
    ON myexample (mycola, UPPER(mycolb), mycolc);
    SELECT mycolc FROM myexample
    WHERE mycola = 55 AND UPPER(mycolb) = 'JONES';
    Restriction & Rule Summary
    The following restrictions apply to function based indexes. You may not index:
    a) LOB columns
    b) REF
    c) Nested table column
    d) Objects types with any of the above data types.
    Function-based indexes must always follow these rules:
    a) Cost Based optimizer only, must generate statistics after the index is created
    b) Can not store NULL values (function can not return NULL under any circumstance)
    c) If a user defined pl/sql routine is used for the function-based index, and is invalidated, the index will become "disabled"
    d) Functions must be deterministic (always return the same value for a known input)
    e) The index owner must have "execute" access on function used in the function-based index. Revocation of the privilege will render the index "disabled"
    f) May have a B-Tree and Bitmap index type only
    g) Can not use expressions that are based on aggregate functions, ie. SUM, AVG etc.
    h) To alter a function-based index as enabled, the function used must be valid, deterministic and the signature of the function matches the signature of the function when it was created.
    Joel P�rez

  • Function based indexes doing full table scan

    Guys,
    I am testing function based indexes and whatever I do
    it is doing a full table scan.
    1)I have set the following init parameters as
    QUERY_REWRITE_ENABLED=TRUE
    QUERY_REWRITE_INTEGRITY=TRUSTED
    2)CREATE INDEX i3 ON emp(UPPER(ename));
    3) ANALYZE TABLE emp COMPUTE STATISTICS
    ANALYZE INDEX I3 COMPUTE STATISTICS
    4) DELETE plan_table;
    5) EXPLAIN PLAN SET statement_id='Test1' FOR
    SELECT ename FROM emp WHERE UPPER(ename) = 'KING';
    6) SELECT LPAD(' ',2*level-2)||operation||' '||options||' '||object_name
    query_plan
    FROM plan_table
    WHERE statement_id='Test1'
    CONNECT BY prior id = parent_id
    START WITH id = 0 order by id
    7) And the query plan shows as
    SELECT STATEMENT
    TABLE ACCESS FULL EMP
    I am using 9.0.1.4 !!!
    Any help is appreciated !!!
    Regards,
    A.Kishore

    One of the many new features in Oracle 8i is the Function-Based Index (we will refrain from using FBI, but only just). This allows the DBA to create indexes on functions or expressions; these functions can be user generated pl/sql functions, standard SQL functions (non-aggregate only) or even a C callout.
    A classic problem the DBA faces in SQL Tuning is how to tune those queries that use function calls in the where clause, and result in indexes created on these columns not to be used.
    Example
    Standard B-Tree index on SURNAME with cost based optimizer
    create index non_fbi on sale_contacts (surname);
    analyze index non_fbi compute statistics;
    analyze table sale_contacts compute statistics;
    SELECT count(*) FROM sale_contacts
    WHERE UPPER(surname) = 'ELLISON';
    Execution Plan
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=17)
    1 0 SORT (AGGREGATE)
    2 1 TABLE ACCESS (FULL) OF 'SALES_CONTACTS' (Cost=3 Card=16 Bytes=272)
    Now we use a function based index
    create index fbi on sale_contacts (UPPER(surname));
    analyze index fbi compute statistics;
    analyze table sale_contacts compute statistics;
    SELECT count(*) FROM sale_contacts WHERE UPPER(surname) = 'ELLISON';
    Execution Plan
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=17)
    1 0 SORT (AGGREGATE)
    2 1 INDEX (RANGE SCAN) OF 'FBI' (NON-UNIQUE) (Cost=2 Card=381 Bytes=6477)
    The function-based index has forced the optimizer to use index range scans (retuning zero or more rowids) on the surname column rather than doing a full table scan (non-index lookup). Optimal performance does vary depending on table size, uniqueness and selectivity of columns, use of fast full table scans etc. Therefore try both methods to gain optimal performance in your database.
    It is important to remember that the function-based B*Tree index does not store the expression results in the index but uses an "expression tree". The optimizer performs expression matching by parsing the expression used in the SQL statement and comparing the results against the expression-tree values in the function-based index. This comparison IS case sensitive (ignores spaces) and therefore your function-based index expressions should match expressions used in the SQL statement where clauses.
    Init.ora Parameters
    The following parameter must be set in your parameter file: QUERY_REWRITE_INTEGRITY = TRUSTED
    QUERY_REWRITE_ENABLED = TRUE
    COMPATIBLE = 8.1.0.0.0 (or higher)
    Grants
    Grants To create function-based indexes the user must be granted CREATE INDEX and QUERY REWRITE, or alternatively be granted CREATE ANY INDEX and GLOBAL QUERY REWRITE. The index owner must have EXECUTE access on the function used for the index. If execute access is revoked then the function-based index will be "disabled" (see dba_indexes).
    Disabled Indexes
    If your function-based index has a status of "disabled" the DBA can do one of the following:
    a) drop and create the index (take note of its current settings)
    b) alter index enable, function-based indexes only, also use disable keyword as required
    c) alter index unusable.
    Queries on a DISABLED index fail if the optimizer chooses to use the index.Here is an example ORA error:
    ERROR at line 1: ORA-30554: function-based index MYUSER.FBI is disabled.
    All DML operations on a DISABLED index also fail unless the index is also marked UNUSABLE and the initialization parameter SKIP_UNUSABLE_INDEXES is set to true.
    Some more Examples
    CREATE INDEX expression_ndx
    ON mytable ((mycola + mycolc) * mycolb);
    SELECT mycolc FROM mytable
    WHERE (mycola + mycolc) * mycolb <= 256;
    ..or a composite index..
    CREATE INDEX example_ndx
    ON myexample (mycola, UPPER(mycolb), mycolc);
    SELECT mycolc FROM myexample
    WHERE mycola = 55 AND UPPER(mycolb) = 'JONES';
    Restriction & Rule Summary
    The following restrictions apply to function based indexes. You may not index:
    a) LOB columns
    b) REF
    c) Nested table column
    d) Objects types with any of the above data types.
    Function-based indexes must always follow these rules:
    a) Cost Based optimizer only, must generate statistics after the index is created
    b) Can not store NULL values (function can not return NULL under any circumstance)
    c) If a user defined pl/sql routine is used for the function-based index, and is invalidated, the index will become "disabled"
    d) Functions must be deterministic (always return the same value for a known input)
    e) The index owner must have "execute" access on function used in the function-based index. Revocation of the privilege will render the index "disabled"
    f) May have a B-Tree and Bitmap index type only
    g) Can not use expressions that are based on aggregate functions, ie. SUM, AVG etc.
    h) To alter a function-based index as enabled, the function used must be valid, deterministic and the signature of the function matches the signature of the function when it was created.
    Joel P�rez

  • Dilemma regarding function based indexes

    Hello,
    I have a dilemma regarding function based indexes.
    I have read Note:66277.1 on the Metalink discussing thoroughly the subject of “Concepts and Usage of Function Based Indexes”.
    This doc was revised on 30-May-2006 so I was sure it referred to 9i and 10g.
    This doc as well as other docs on the web claim that in order to use FBI (function based indexes) one must set the following parameters (can be done also at session level)
    QUERY_REWRITE_ENABLED = TRUE
    QUERY_REWRITE_INTEGRITY = TRUSTED
    Also the schema that is owner of the FBI should be granted with QUERY REWRITE sys priv and statistics should be collected since FBI is usable only by CBO (cost based optimizer).
    I have tested it and it works, my problem was that it worked
    (1)     Without granting the QUERY REWRITE to the owning schema.
    (2)     QUERY_REWRITE_ENABLED was set to false.
    (3)     QUERY_REWRITE_INTEGRITY was set to enforced.
    I have conducted my tests on 9.2.0.6 and found no evidence in the docs (10g) saying the above is required or not.
    I found at http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:1197786003246 the following:
    “Oracle9iR2 relaxed this so that the FBI on the builtin function may be used.”
    so I have tested it with my own function:
    create or replace function upper2( p_str in varchar2 ) return
    varchar2 DETERMINISTIC
    as
    begin
    return upper(p_str);
    end;
    =>
    Also (yes you guessed right), without any privilege granted nor parameter setting the optimizer picked my FBI.
    Can anyone refer me to a place documenting this behavior as a correct one?
    Other comments?
    Regards,
    Tal Olier ([email protected])

    Got an answer from Oracle support:
    19-DEC-06 18:04:31 GMT
    (Update for record id(s): 101017780,101017796)
    QUESTION
    ========
    Questions about the options required in 10g related to Function Based Indexes, and the correct
    behaviors associated with them.
    ANSWER
    ======
    For 10g:
    These requirements are no longer true in 10g. This has already clarified by
    development in the Bug 3999326 which is available on metalink.
    For 9I:
    For the creation of a function-based index in your own schema, you must be
    granted the QUERY REWRITE system privileges. To create the index in another
    schema or on another schema's tables, you must have the CREATE ANY INDEX
    and GLOBAL QUERY REWRITE privileges.
    You must have the following initialization parameters defined to create a
    function-based index:
    QUERY_REWRITE_INTEGRITY set to TRUSTED
    QUERY_REWRITE_ENABLED set to TRUE
    COMPATIBLE set to 8.1.0.0.0 or a greater value
    Additionally, to use a function-based index:
    The table must be analyzed after the index is created.
    The query must be guaranteed not to need any NULL values from the indexed
    expression, since NULL values are not stored in indexes.
    However, in 9.2.0.4 patchset, these prerequisites do not apply and one can
    create function-based indexes without any of the above to be true. This is not
    the case in 9.2.0.3, not in 8.1.7.
    Reference: Oracle 9i R2 Administrators Guide
    So as mentioned above that is why you didnt have any errors
    Please back to us if any further information is need, and we will be pleased to
    assist you further.
    Thank You,
    Best Regards,
    Mina Anes

  • Function-Based Indexes for 8.1.6 SE and 9iAS

    I have installed the 9iAS Portal into a 8.1.6 SE database, and I cannot get the Function-Based Index feature to turn on. I have set QUERY_REWRITE_INTEGRITY=trusted, QUERY_REWRITE_ENABLED=true and COMPATIBLE="8.1.0.0.0". The feature will still not enable.
    I have 2 questions:
    1. Is there anything else I can do to turn this feature on.
    2. If not, do I have to upgrade to 8.1.7 or to 8.1.* Enterprise Edition to make use of this feature.

    Could you give the statement for the index you have used, the query you try to do and a description of columns and datatypes of the table? How do you know/check that is doesn't work? Execution plan, errors?...

  • ORA-04091 (table string.string is mutating) and Function-Based Index

    I've encountered a problem with DELETEing from a table when that table has a function-based index on it. The following demonstrates this:
    SQL> CREATE OR REPLACE FUNCTION get_employee_location(p_empno IN number)
      2  RETURN varchar2
      3  DETERMINISTIC
      4  IS
      5  l_return_value   varchar2(20);
      6  BEGIN
      7  SELECT loc
      8  INTO   l_return_value
      9  FROM   dept
    10  WHERE  deptno = (SELECT
    11                   e.deptno
    12                   FROM emp e
    13                   WHERE empno = p_empno);
    14  return l_return_value;
    15  end;
    16  /
    Function created.
    SQL> create index location_idx on emp (get_employee_location(empno));
    Index created.
    SQL> delete from emp;
    delete from emp
    ERROR at line 1:
    ORA-04091: table SCOTT.EMP is mutating, trigger/function may not see it
    ORA-06512: at "SCOTT.GET_EMPLOYEE_LOCATION", line 7------------------------------------------------
    The question is: How can I successfully DELETE FROM emp but keep my function-based index in place?
    Thanks
    Andy

    'Being able to' is 'being able to', but
    it is dangerous to declare "DETERMINISTIC" for non-deterministic function.
    The following problem happens on non-deterministic function index.
    SQL> update dept set loc = 'NEWYORK' where deptno=10;
    1 row updated.
    SQL> commit;
    Commit complete.
    SQL> select * from emp where get_employee_location(deptno)='NEWYORK';
    no rows selected
    SQL> select * from dept;
        DEPTNO DNAME          LOC
            10 ACCOUNTING     NEWYORK
            20 RESEARCH       DALLAS
            30 SALES          CHICAGO
            40 OPERATIONS     BOSTON
    SQL> select empno,ename from emp where get_employee_location(deptno)='NEW YORK';
         EMPNO ENAME
          7782 CLARK
          7839 KING
          7934 MILLER
    SQL> select empno,ename,get_employee_location(deptno) from emp where deptno=10;
         EMPNO ENAME      GET_EMPLOYEE_LOCATION(DEPTNO)
          7782 CLARK
          7839 KING
          7934 MILLER
    SQL> select empno,ename,get_employee_location(deptno) from emp where get_employee_location(deptno)='NEW YORK';
         EMPNO ENAME      GET_EMPLOYEE_LOCATION(DEPTNO)
          7782 CLARK      NEW YORK
          7839 KING       NEW YORK
          7934 MILLER     NEW YORK
    SQL> drop index location_idx ;
    Index dropped.
    SQL> select empno,ename from emp where get_employee_location(deptno)='NEW YORK';
    no rows selected

  • Storage for Foreign Keys and Function based indexes

    This may well be the silliest question of the day, but is it possible to specify the storage for a Foreign key or a function based index? I'm not even sure that it would make sense.

    Well, a foreign key constraint is not a segment, nor is any other type of constraint. However, a function-based index is a segment, just like any other index. So, in that case, specify a tablespace, just like you would with any other index.
    Something like this:
    create index my_fbi on my_tab(upper(last_name)) tablespace my_index_tablespace;
    -Mark
    Message was edited by:
    mbobak
    Fixed minor typo.

  • Intermedia and function-based indexes

    Is it valid to use function-based indexing to create an intermedia index type ?

    I am interested in this, what's your motivation for function-based index in interMedia text? What kind of function are you going to design?
    Honglin

  • Function-based index with OR in the wher-clause

    We have some problems with functin-based indexes and
    the or-condition in a where-clause.
    --We use Oracle 8i (8.1.7)
    create table TPERSON(ID number(10),NAME varchar2(20),...);
    create index I_NORMAL_TPERSON_NAME on TPERSON(NAME);
    create index I_FUNCTION_TPERSON_NAME on TPERSON(UPPER(NAME));
    The following two statements run very fast on a large table
    and the execution-plan asure the usage of the indexes
    (-while the session is appropriate configured and the table is analyzed):
    1)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%';
    2)     select count(ID) from TPERSON where NAME like 'Mil%' or (3=5);
    In particular we see that a normal index is used while the where-clause contains
    an OR-CONDITION.
    But if we try the similarly select-statement
    3)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%' or (3=5);
    the CBO will not use the function-index I_FUNCTION_TPERSON_NAME and we have a full table scan in the execution-plan.
    (This behavior we only expect with views but not with indexes.)
    We ask for an advice like a hint, which enable the CBO-usage
    of function-based indexes in connection with OR.
    This problem seems to be artificial because it contains this dummy logic:
         or (3=5).
    This steams from an prepared statement, where this kind of boolean
    flag reduce the amount of different select-statements needed for
    covering the hole business-logic, while using bind-variables for the
    concrete query-parameters.
    A more realistic (still boild down) version of our select-statement is:
    select * FROM TPERSON
    where (upper(NAME) like 'MIL%' or (NAME is null))
    and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
    and ...;
    thank you for time..
    email: [email protected]

    In the realistic statement you write :
    select * FROM TPERSON
    where (upper(NAME) like 'MIL%' or (NAME is null))
    and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
    and ...;
    as far as i know, NULL values are not indexed, "or (NAME is NULL)" have to generate a full table scan.
    HTH
    We have some problems with functin-based indexes and
    the or-condition in a where-clause.
    --We use Oracle 8i (8.1.7)
    create table TPERSON(ID number(10),NAME varchar2(20),...);
    create index I_NORMAL_TPERSON_NAME on TPERSON(NAME);
    create index I_FUNCTION_TPERSON_NAME on TPERSON(UPPER(NAME));
    The following two statements run very fast on a large table
    and the execution-plan asure the usage of the indexes
    (-while the session is appropriate configured and the table is analyzed):
    1)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%';
    2)     select count(ID) from TPERSON where NAME like 'Mil%' or (3=5);
    In particular we see that a normal index is used while the where-clause contains
    an OR-CONDITION.
    But if we try the similarly select-statement
    3)     select count(ID) FROM TPERSON where upper(NAME) like 'MIL%' or (3=5);
    the CBO will not use the function-index I_FUNCTION_TPERSON_NAME and we have a full table scan in the execution-plan.
    (This behavior we only expect with views but not with indexes.)
    We ask for an advice like a hint, which enable the CBO-usage
    of function-based indexes in connection with OR.
    This problem seems to be artificial because it contains this dummy logic:
         or (3=5).
    This steams from an prepared statement, where this kind of boolean
    flag reduce the amount of different select-statements needed for
    covering the hole business-logic, while using bind-variables for the
    concrete query-parameters.
    A more realistic (still boild down) version of our select-statement is:
    select * FROM TPERSON
    where (upper(NAME) like 'MIL%' or (NAME is null))
    and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
    and ...;
    thank you for time..
    email: [email protected]

  • Creation of function based index using escape

    Hello,
    I have the following SQL, sometimes performing bad:
    SELECT DISTINCT UPPER(A.PROCESSIDCODE), UPPER(A.RULENAME), CHARSET
    FROM XIB_DETECT A, XIB_PROCESSIDPROPERTIES B, XIB_RULES C
    WHERE ( A.KEY1 = :P1 OR ( :P1 like REPLACE(REPLACE(REPLACE(REPLACE(KEY1,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\' AND A.REGFLAGS1 = 'Y') OR A.KEY1 = '*' AND A.REGFLAGS1 = 'Y')
    AND (A.KEY2 = :P2 OR ( :P2 like REPLACE(REPLACE(REPLACE(REPLACE(KEY2,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\' AND A.REGFLAGS2 = 'Y') OR (A.KEY2 IS NULL AND A.REGFLAGS2 IS NULL ) )
    AND (A.KEY3 = :P3 OR ( :P3 like REPLACE(REPLACE(REPLACE(REPLACE(KEY3,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\' AND A.REGFLAGS3 = 'Y') OR (A.KEY3 IS NULL AND A.REGFLAGS3 IS NULL ) )
    AND (A.KEY4 = :P4 OR ( :P4 like REPLACE(REPLACE(REPLACE(REPLACE(KEY4,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\' AND A.REGFLAGS4 = 'Y') OR (A.KEY4 IS NULL AND A.REGFLAGS4 IS NULL ) )
    AND (A.KEY5 = :P5 OR ( :P5 like REPLACE(REPLACE(REPLACE(REPLACE(KEY5,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\' AND A.REGFLAGS5 = 'Y') OR (A.KEY5 IS NULL AND A.REGFLAGS5 IS NULL ) )
    AND (A.KEY6 IS NULL OR A.KEY6 = '*' AND REGFLAGS6 = 'Y')
    AND (A.KEY7 IS NULL OR A.KEY7 = '*' AND REGFLAGS7 = 'Y')
    AND (A.KEY8 IS NULL OR A.KEY8 = '*' AND REGFLAGS8 = 'Y')
    AND (A.KEY9 IS NULL OR A.KEY9 = '*' AND REGFLAGS9 = 'Y')
    AND (A.KEY10 IS NULL OR A.KEY10 = '*' AND REGFLAGS10 = 'Y')
    AND ( ( A.PROCESSIDCODE IS NOT NULL AND UPPER(A.PROCESSIDCODE) = UPPER(B.PROCESSIDCODE) AND A.XLEVEL = B.XLEVEL AND B.ACTIVEFLAG = 'Y' )
    OR ( A.RULENAME IS NOT NULL AND UPPER(A.RULENAME) = UPPER(C.RULENAME) AND A.XLEVEL = C.XLEVEL AND C.ACTIVEFLAG = 'Y' ) );
    Now I want to create a function based index on the key1 column:
    CREATE INDEX xib_detect_ix ON xib_detect (REPLACE(REPLACE(REPLACE(REPLACE(KEY1,'%', '\%'),'_', '\_'),'?', '_'),'*','%') escape '\') TABLESPACE ... ONLINE;
    However, this is not working with "escape" '\', throwing: ORA-00907: missing right parenthesis
    Any idea how to create an index on this construct with "escape"?
    Database version is 10.2.0.3.
    Thanks a lot.
    Regards
    Oliver

    Hi,
    You can get the "missing right parenthesis" error for many different syntax errors.
    In this case, you really are missing a right parenthesis.  Your statement has 5 left '('s, but only 4 right ')'s.  It's easy to see this if you format your code:
    CREATE  INDEX xib_detect_ix
    ON  xib_detect ( REPLACE ( REPLACE ( REPLACE ( REPLACE ( KEY1
                     escape '\'
    ESCAPE is an option that you can use with the LIKE operator.  It gives you a mechanism for cancelling the special meaning of symbols like '%'.    You're not using the LIKE operator to create the index.  You're only using REPLACE, and no characters have any special meaning in REPLACE, so there's no way (or reason) to escape them.  Use ESCAPE in queries that use LIKE, when appropriate.

  • FUNCTION-BASED INDEX ( ORACLE 8I NEW FEATURE )

    제품 : ORACLE SERVER
    작성날짜 : 2004-08-16
    FUNCTION-BASED INDEX ( ORACLE 8I NEW FEATURE )
    ==============================================
    SCOPE
    10g Standard Edition(10.1.0) 이상 부터 Function-based Index 기능이 지원된다.
    Explanation
    1. 개요
         Function-based index는, 함수(function)이나 수식(expression)으로 계산
    된 결과에 대해 인덱스를 생성하여 사용할 수 있는 기능을 제공한다.
         질의 수행 시 해당 함수나     수식을 처리하여     결과를 가져 오는 것이 아니라,
         인덱스 형태로 존재하는 미리 계산되어 있는 결과를 가지고 처리하므로
         성능 향상을 기할 수 있다.
    2. 제약사항
    1) aggregate function 에 대한 function-based index 생성 불가.
    (예 : sum(...) )
    2) LOB, REF, nested table 컬럼에 대한 function-based index 생성 불가.
    3. 주요 특징
         1) cost-based optimizer에 의해 사용됨.
         2) B*Tree / bitmap index로 생성 가능.
         3) 산술식 (arithmetic expression), PLSQL function, SQL built-in
    function 등에 적용 가능.
         4) 함수나 수식으로 처리된 결과에 대한 range scan 가능
         5) NLS SORT 지원
         6) SELECT/DELETE를 할 때마다 함수나 수식의 결과를 계산하는 것이 아니라
         INSERT/UPDATE 시 계산된 값을 인덱스에 저장.
         7) 질의 속도 향상
         8) object column이나 REF column에 대해서는 해당 object에 정의된
         method에 대해 function-based index 생성 가능.
    4. 생성 방법
         CREATE [UNIQUE | BITMAP ] INDEX <index_name>
         ON <tablename> (<index-expression-list>)
         <index-expression-list> -> { <column_name> | <column_expression> }
         예) CREATE INDEX EMP_NAME_INDEX ON EMP (UPPER(ENAME));
         CREATE INDEX EMP_SAL_INDEX ON EMP( SAL + COMM, empno);
         * Function-based index를 생성하기 위해서는 QUERY REWRITE 권한이
         부여 되어 있어야만 한다.
         예) GRANT QUERY REWRITE TO SCOTT;
    5. Function-Based Index 사용을 위한 사전 작업
         1) Function-based index는 cost based optimizer에서만 사용 가능하므로,
         테이블에 대해 미리 analyze 해 주는 것이 바람직하다.
         그리고 init 파일에서 OPTIMIZER_MODE 를 FIRST_ROWS 나 ALL_ROWS 등으
    로 지정하거나 HINT 등을 사용하여 cost based optimizer가 사용되도록
    한다.
         2) init 파일에서 COMPATIBLE 파라미터 값을 8.1 이상으로 설정되어 있어야
    한다.
         ( 예 : COMPATIBLE = 8.1.6 )
         3) session/instance level 에서 QUERY_REWRITE_ENABLED 값이 TRUE 지정
    되어 있어야 한다.
         ( 예 : ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE; )
    6. 예제
         1) init 파라미터에서 다음과 같이 지정
         compatible = 8.1.6 (반드시 8.1이상이어야 한다)
         query_rewrite_enabled = true
         query_rewrite_integrity = trusted
         2) SCOTT 유저에서 function_based_index 생성
         create index idx_emp_lower_ename
         on emp
         ( lower(ename) ) ;
         3) EMP table analyze
         analyze table emp compute statistics ;
         4) PLAN_TABLE 생성
         @ ?/rdbms/admin/utlxplan.sql
         5) Cost based optimizer 선택
         alter session set optimizer_mode = FIRST_ROWS ;
         6) Query 실행
         explain plan set statement_id='qry1' FOR
         select empno, ename
         from emp
         where lower(ename) = 'ford' ;
         7) PLAN 분석
         SELECT LPAD(' ',2*level-2)||operation||' '||options||' '||object_name query_plan
         FROM plan_table
         WHERE statement_id='qry1'
         CONNECT BY prior id = parent_id
         START WITH id = 0 order by id ;
         -> 결과
         QUERY_PLAN
         SELECT STATEMENT
         TABLE ACCESS BY INDEX ROWID EMP
         INDEX RANGE SCAN IDX_EMP_LOWER_ENAME
    7. 결론
    Function-based index는 적절하게 사용될 경우 성능상의 많은 이점을 가져
    온다. Oracle8i Designing and Tuning for Performance에서도 가능한 한
    Function-based index를 사용하는 것을 권장하고 있으며, LOWER(), UPPER()
    등의 함수를 사용하여 불가피하게 FULL TABLE SCAN을 하는 경우에 대해서도
    효과적으로 처리해 줄 수 있는 방안이라 할 수 있다.
    Reference Documents
    -------------------

    Partha:
    From the Oracle8i Administrators Guide:
    "Table owners should have EXECUTE privileges on the functions used in function-based indexes.
    For the creation of a function-based index in your own schema, you must be
    granted the CREATE INDEX and QUERY REWRITE system privileges. To create
    the index in another schema or on another schemas tables, you must have the
    CREATE ANY INDEX and GLOBAL QUERY REWRITE privileges."
    Hope this helps.
    Peter

Maybe you are looking for

  • Making sql faster not in pl.sql but in sql

    this sql takes a long time running from Application to oracle database 11.2.0.3.0 on win 2008 r2 in Toad it runs much faster any suggestions to make it faster in SQL, this is dynamic code where 1500000 is bind variable passed from application side. t

  • DATA EXTRACTION FROM ORACLE & SYBASE

    Hello members... Good day. This is my first posting in this site. I am new to Oracle and have a question regarding Data extraction from Oracle and Sybase. My project has two applications one having Oracle as the database and the other has Sybase as t

  • Number of resources consumed ?

    Experts, For 100 identical machines, single resource is created with n=100 in capacity tab. Requirement is, during process order creation, system should provide a provision for entering the actual number of m/c to be consumed. e.g before saving  user

  • I am unable to download adobe reader

    I have been trying to download adobe reader with no success.  I am using windows vista - and it starts to download then I get an error message after 66% downloaded which states "General Installation Error".  I used to be able to open pdf files but re

  • Premiere Pro CS6 not locating media, freezing

    For the last couple of days, Premiere Pro on my laptop (15" Apple Retina MacBook Pro, 12gb ram, 2.7GHz i7 - USB 3.0 Lacie drive) has been having trouble locating media. When I open a project, the "Locating Media" diologe shows the progress bar start