Function Based Index on Date Column

Hi All,
I need to execute a query like this :
SELECT * FROM ORDERS WHERE APPROVE_DATE IS NULL
I read anywhere that this will cause unnecessary FTS so that I should create function based index.
I have tried one below , but not sure that this is correct approach :
CREATE INDEX idx_1
ON ORDERS (NVL(APPROVE_DATE, '01-JAN-1900'));
SELECT * FROM ORDERS WHERE NVL(APPROVE_DATE, '01-JAN-1900') = '01-JAN-1900'
Is this a correct approach ?
Thank you,
xtanto

A SQL_TRACE output will explain clearly what Justin has stated.
I have created a table T based on all_objects.
SQL> desc t
Name                                      Null?    Type
OWNER                                     NOT NULL VARCHAR2(30)
OBJECT_NAME                               NOT NULL VARCHAR2(30)
SUBOBJECT_NAME                                     VARCHAR2(30)
OBJECT_ID                                 NOT NULL NUMBER
DATA_OBJECT_ID                                     NUMBER
OBJECT_TYPE                                        VARCHAR2(19)
CREATED                                            DATE
LAST_DDL_TIME                             NOT NULL DATE
TIMESTAMP                                          VARCHAR2(19)
STATUS                                             VARCHAR2(7)
TEMPORARY                                          VARCHAR2(1)
GENERATED                                          VARCHAR2(1)
SECONDARY                                          VARCHAR2(1)
CASE I_
SQL> select count(1) from t
  2  /
  COUNT(1)
    934320
SQL> select count(1) from t where created is null
  2  /
  COUNT(1)
      2376The number of null values in CREATED column is proportionately very small.
Now i execute the query without function based index.
select *
  from t
where created is null
call     count       cpu    elapsed       disk      query    current        rows
Parse        1      0.00       0.09          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch      160      0.04       0.10          0      12662          0        2376
total      162      0.04       0.19          0      12662          0        2376
Rows     Execution Plan
      0  SELECT STATEMENT   GOAL: ALL_ROWS
   2376   TABLE ACCESS   GOAL: ANALYZED (FULL) OF 'T' (TABLE)And here is the query that uses the function based index
select *
  from t
where nvl(created,to_date('01-01-1900','DD-MM-YYYY')) = to_date('01-01-1900','DD-MM-YYYY')
call     count       cpu    elapsed       disk      query    current        rows
Parse        1      0.01       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch      160      0.01       0.01          0        698          0        2376
total      162      0.03       0.01          0        698          0        2376
Rows     Execution Plan
      0  SELECT STATEMENT   GOAL: ALL_ROWS
   2376   TABLE ACCESS   GOAL: ANALYZED (BY INDEX ROWID) OF 'T' (TABLE)
   2376    INDEX   GOAL: ANALYZED (RANGE SCAN) OF 'T_FN_IDX' (INDEX)Its very obvious from the above output that the Function Based Index as increased the performance.
CASE II_
SQL> select count(1) from t
  2  /
  COUNT(1)
    934320
SQL> select count(1) from t where created is null
  2  /
  COUNT(1)
    202168Now the null values in the CREATED column is proportionately large than the first test case.
Now lets see without using the function based index
select *
  from t
where created is null
call     count       cpu    elapsed       disk      query    current        rows
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch    13479      0.46       0.71          2      25832          0      202168
total    13481      0.46       0.71          2      25832          0      202168
Rows     Execution Plan
      0  SELECT STATEMENT   GOAL: ALL_ROWS
202168   TABLE ACCESS   GOAL: ANALYZED (FULL) OF 'T' (TABLE)Now iam trying to use the function based index
select *
  from t
where nvl(created,to_date('01-01-1900','DD-MM-YYYY')) = to_date('01-01-1900','DD-MM-YYYY')
call     count       cpu    elapsed       disk      query    current        rows
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch    13479      0.54       0.84          0      33826          0      202168
total    13481      0.54       0.84          0      33826          0      202168
Rows     Execution Plan
      0  SELECT STATEMENT   GOAL: ALL_ROWS
202168   TABLE ACCESS   GOAL: ANALYZED (FULL) OF 'T' (TABLE)Its obvious from the result that oracle has decided to go for a FULL TABLE SCAN even when an index was available.
So just having a function based index is not going to increase the query performance. There are lot of other factors to be considered as stated above.
Thanks,
Karthick.

Similar Messages

  • Function based indexes in Data Modeler 3.0

    Trying to create a function based index in DATA MODELER 3.0 but cannot find a way to do it. When I reverse engineer (import from DATA DICTIONNARY) an existing table that contains such an object, the index appears in the physical model as a regular index. I guess this functionnality is not yet available...
    Thanks.

    Hi,
    You can create a function-based Index by going to the Properties dialog for the Index in the Relational model (not the Physical model). If you select the Index Expression tick box, you can then enter the expression into the Expression text area.
    David

  • Function based indexing v8.1.7 not working

    I have created a function based index on a column and when I run my query although I get the correct results I seem to be doing a full table scan instead of using the index.
    Are there any known bugs or additional parameter setting for function based indexing in 8i ?
    Thanks
    Bob I

    Robert
    To use Functional Index you to set following parameters in INIT.ORA, Compatiable should be more than 8.1.0
    query_rewrite_enabled = TRUE
    query_rewrite_integrity = TRUSTED
    Compatiable = 8.1.7.0
    optimizer = Choose
    Create index indexname on table (lower(column));
    then analyze table
    Analyze table tablename compute statistics;
    Regards
    Shailesh
    null

  • Function Based Index - Query Performance

    HI,
    Good Day to All..
    I'd like to use function based indexes on following column(to_char(ps.user_pc_id)).
    Whereas this column is part of PRIMARY KEY.
    Is it possible to create a function based index on PRIMARY KEY Column?
    Attached below is the query with the explain plan ...
    TO_CHAR Expression - Performance
    Thanks for your reply.

    DTYLER_APP@pssdev2> create table dt_fbi_pk(id varchar2(20));
    Table created.
    DTYLER_APP@pssdev2> drop table dt_fbi_pk;
    Table dropped.
    DTYLER_APP@pssdev2> create table dt_fbi(id number);
    Table created.
    DTYLER_APP@pssdev2> create index dt_fbi_idx on dt_fbi(to_char(id));
    Index created.
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_pk primary key (id);
    Table altered.
    DTYLER_APP@pssdev2> select constraint_name,constraint_type, index_name from user_constraints where table_name='DT_FBI';
    CONSTRAINT_NAME                C INDEX_NAME
    DT_FBI_PK                      P DT_FBI_PK
    1 row selected.When we created the primary key constraint, Oracle created a new index rather than using the existing one because....
    DTYLER_APP@pssdev2> alter table dt_fbi drop primary key;
    Table altered.
    DTYLER_APP@pssdev2> select index_name from user_indexes where table_name ='DT_FBI';
    INDEX_NAME
    DT_FBI_IDX
    1 row selected.
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_pk primary key (id) using index dt_fbi_idx;
    alter table dt_fbi add constraint dt_fbi_pk primary key (id) using index dt_fbi_idx
    ERROR at line 1:
    ORA-14196: Specified index cannot be used to enforce the constraint.
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_uk unique(id) using index dt_fbi_idx;
    alter table dt_fbi add constraint dt_fbi_uk unique(id) using index dt_fbi_idx
    ERROR at line 1:
    ORA-14196: Specified index cannot be used to enforce the constraint.We can't use a function based index to enforce a unique or primary key constraint. Changing the syntax does not help..
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_uk unique(TO_CHAR(id)) using index dt_fbi_idx;
    alter table dt_fbi add constraint dt_fbi_uk unique(TO_CHAR(id)) using index dt_fbi_idx
    ERROR at line 1:
    ORA-00904: : invalid identifierWe can create a unique index however
    DTYLER_APP@pssdev2> drop index dt_fbi_idx;
    Index dropped.
    DTYLER_APP@pssdev2> create unique index dt_fbi_idx on dt_fbi(to_char(id));
    Index created.but we still can't use it to enforce a unique or primary key constraint
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_pk primary key (id) using index dt_fbi_idx;
    alter table dt_fbi add constraint dt_fbi_pk primary key (id) using index dt_fbi_idx
    ERROR at line 1:
    ORA-14196: Specified index cannot be used to enforce the constraint.
    DTYLER_APP@pssdev2> alter table dt_fbi add constraint dt_fbi_uk unique(id) using index dt_fbi_idx;
    alter table dt_fbi add constraint dt_fbi_uk unique(id) using index dt_fbi_idx
    ERROR at line 1:
    ORA-14196: Specified index cannot be used to enforce the constraint.So no, you can't use it for a primary key. If you just want to enforce uniqueness then yes, you can do it with a unique index, but not a constraint.
    DTYLER_APP@pssdev2> select * from v$version;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE    10.2.0.4.0      Production
    TNS for Linux: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    5 rows selected.HTH
    Daviid

  • Function based indexes info,pls let me know data dictionary table name?

    Hi,
    pls let me know,Where can we find Function based index information ,that is data dictionary table name,.
    that is information like function used, column name.
    Thanks,
    KUmar.

    all_ind_expressions

  • Unable to create function based Index

    Hi All,
    I created a function as below:
    create or replace function eqx_oklb_term_date_nvl(pin_term_date date)
    return date
    deterministic
    is
    l_sub_date date := sysdate+1;
    l_return_value date := l_sub_date;
    begin
    l_return_value := nvl(pin_term_date, l_sub_date);
    return l_return_value;
    exception
    when others
    then
    l_return_value := l_sub_date;
    return l_return_value;
    end eqx_oklb_term_date_nvl;
    Now trying to create a function based index using below code:
    create index EQX_OKC_K_LINES_B_N4 on OKC.OKC_K_LINES_B(EQX_OKLB_TERM_DATE_NVL(DATE_TERMINATED))
    logging
    tablespace EQIXDATA
    noparallel;
    Encountered Error:
    SQL Error: ORA-00904: "EQX_OKLB_TERM_DATE_NVL": invalid identifier
    00904. 00000 - "%s: invalid identifier"
    *Cause:   
    *Action:
    I can successfully query dba_objects for the function.
    Owner Object_name object_id object_type last_ddl_time status
    APPS     EQX_OKLB_TERM_DATE_NVL     11764623     FUNCTION     3/4/2013 9:44:57 PM     VALID
    I can also query the function using dual.
    select eqx_oklb_term_date_nvl(null) nvl_date from dual;
    nvl_date
    3/5/2013 9:53:59 PM
    I have given grants of the function to both schemas APPS/OKC
    grant all on eqx_oklb_term_date_nvl to okc;
    grant all on eqx_oklb_term_date_nvl to apps;
    The column date_terminated in table okc_k_lines_b is a date. I've checked that.
    Stuck here. Please help.
    Thanks in advance,
    Rahul

    Hi,
    To follow up, the below code resolved the issue:
    create index EQX_OKC_K_LINES_B_N4 on okc_k_lines_b(apps.eqx_oklb_term_date_nvl(date_terminated))
    logging
    tablespace eqixdata
    noparallel;
    -- qualifying the custom function name with schema name resolved the issue.
    Thanks,
    Rahul

  • Function Based Index

    Hi All,
    select * from v$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
    PL/SQL Release 11.1.0.7.0 - Production
    CORE    11.1.0.7.0      Production
    TNS for Linux: Version 11.1.0.7.0 - Production
    NLSRTL Version 11.1.0.7.0 - ProductionI have a 10GB partitioned table which has INVOICE_DUE_DATE column. Table is partitioned on CREATION_DATE. All records which has CREATION_DATE less than 01-jan-2010 have INVOICE_DUE_DATE set to NULL and new records (for year 2011)are updated with recent date(i.e. sysdate) by 'due_date_update' process. Some developers want indexing on INVOICE_DUE_DATE column as they have SLA critical reports running against INVOICE_DUE_DATE column. (where INVOICE_DUE_DATE > :B1) B1 could be any date in 2011.
    As of now, ~85% records are having INVOICE_DUE_DATE set to NULL.
    Given above scenarios,Can i use function based index to index all rows where INVOICE_DUE_DATE is any date in 2011 ?
    Edited by: OraDBA02 on Jan 11, 2011 4:00 AM

    OraDBA02 wrote:
    Given above scenarios,Can i use function based index to index all rows where INVOICE_DUE_DATE is any date in 2011 ?I suppose you could, but you might not need to. If you had an index that just contained the INVOICE_DUE_DATE column it wouldn't index the NULL values anyways.

  • Impdp not importing function based index correctly.

    We noticed that a process running in our develop database was running much faster than in the production database. After investigating we found that on the development database the process was using an index on the main large table and on the production database the index was ignored and full table scans of the large table were being used.
    The data in the tables was the same, statistics were up-to-date, etc. Looking closer we saw that the index on the production database was function based because it had the DESC keyword on one column in the index. On the development database all columns of the index were ASC and thus it was a "normal" index. This was very confusing since we had just refreshed the development database from production using expdp/impdp. I ran impdp with the sqlfiles option to capture the DDL from the export file for the index in question from the production database:
    CREATE UNIQUE INDEX "SYSADM"."PS_SF_1098_ITEM" ON "SYSADM"."PS_SF_1098_ITEM" ("EMPLID", "SF_TIN", "CALENDAR_YEAR", "SEQ_NO" DESC, "DTL_SEQ_NBR")
    PCTFREE 10 INITRANS 2 MAXTRANS 255
    STORAGE(INITIAL 40960 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "PSINDEX" ;
    I then dropped the table/index in the development database and reimported just this one table. Sure enough, the index wasn't created as a function based index (no DESC keyword on SEQ_NO column):
    CREATE UNIQUE INDEX "SYSADM"."PS_SF_1098_ITEM" ON "SYSADM"."PS_SF_1098_ITEM" ("EMPLID", "SF_TIN", "CALENDAR_YEAR", "SEQ_NO", "DTL_SEQ_NBR")
    PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 40960 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "PSINDEX" ;
    I've researched this extensively and can't find any information on why this is happening. Any ideas before I open a SR?
    BTW.... version is 11.1.0.7 patchset 31 on Windows Server 2003. Both dev and prod environments are identical.
    Thanks,
    Dan

    Working on something else I noticed the following two "hidden" init.ora parameters in both my dev and production databases:
    *._disable_function_based_index=TRUE
    *._ignore_desc_in_index=TRUE
    The first parameter explains why the index (function based) was being ignored in my production database. The second explains why the index is created without the DESC keyword in my dev database from an export from my prod database. I guess you do learn something new every day :)
    These databases are used by Peoplesoft applications and I found several posts saying that function based indexes created by Peoplesoft were causing performance and/or data validity problems and users were instructed to set the above parameters so the FIB's weren't used. So, everything is working as expected/designed. I will contact Peoplesoft Tech Support to see if users are still encouraged to set the above parameters.
    Dan

  • Function-based indexes don't seem to work in Oracle 8.1.5?

    Hi,
    What gives? What am I doing wrong? I have a table AIRPORT with a column (varchar2(64)) which I have specified a function based index for, but I can't get SQL wueries to use it!!!! the following SQL executes a FULL TABLE SCAN:
    select /*+ index (a idx_upper_cityname) */ *
    from airport a
    where nls_upper(cityName) = 'dfdf'
    ...as does...
    select *
    from airport a
    where nls_upper(cityName) = 'dfdf'
    Table and index code is as follows:
    CREATE TABLE airport
    id NUMBER NOT NULL,
    citycode VARCHAR2(3) NOT NULL,
    cityname VARCHAR2(64) NOT NULL,
    state VARCHAR2(2),
    country VARCHAR2(2) NOT NULL,
    region CHAR(1),
    airportcode VARCHAR2(3) NOT NULL,
    airportname VARCHAR2(64),
    code VARCHAR2(4)
    drop index idx_upper_cityname
    CREATE INDEX idx_upper_cityname ON airport nls_upper(substr(cityName, 0, 64) )
    Environment is as follows:
    Oracle8i v8.1.5 running on WinNT v4.0 (SP 5)
    Client is running on the same machine
    thanks in advance,
    Alexander

    New data point: when I set the handler in my logging.properties file thusly,
    org.apache.catalina.core.ContainerBase.[Catalina].[info-dev].[/infoisland].level = ALL
    org.apache.catalina.core.ContainerBase.[Catalina].[info-dev].[/infoisland].handlers = java.util.logging.ConsoleHandlerI get 0 bytes in the info-dev log (which used to have the aforementioned expception in it). Where is my console going?

  • 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

  • Is Function-based Index useless ?

    I have a table with 1+ mln records, which has lastupdate (date) column.
    In order to improve performance for it, I created Function-based index on Trunc(lastupdate) column:
    CREATE INDEX idx_trunc_lastupdate
    ON ms_test(TRUNC(LASTUPDATE))
    When I run Explain Plan for my query
    SELECT * FROM ms_test
    WHERE trunc(lastupdate)=trunc(sysdate)
    it chooses Full table scan instead of index.
    Even when I include hint like this
    SELECT /*+ index(MS_TEST, idx_trunc_lastupdate) */
    * FROM ms_test
    WHERE trunc(lastupdate)=trunc(sysdate)
    Explain Plan still chooses full table scan.
    What is wrong here, or maybe hints don't work with function-based indexes ?
    Thanks

    Todd,
    You're right. I can't remember when or where I read that, but I think I tested it and it was true at the time. I just tested it using 8.1.7 and, as you said, it is no longer necessary to match case and whitespace. I included my tests below.
    Barbara
    SQL> CREATE TABLE test_table AS SELECT created FROM user_objects
      2  /
    Table created.
    SQL> CREATE INDEX t_fbi ON test_table (TRUNC (created))
      2  /
    Index created.
    SQL> ANALYZE TABLE test_table
      2  COMPUTE STATISTICS
      3  FOR TABLE
      4  FOR ALL INDEXES
      5  FOR ALL INDEXED COLUMNS
      6  /
    Table analyzed.
    SQL> ALTER SESSION SET QUERY_REWRITE_ENABLED=TRUE
      2  /
    Session altered.
    SQL> ALTER SESSION SET QUERY_REWRITE_INTEGRITY=TRUSTED
      2  /
    Session altered.
    SQL> SET AUTOTRACE ON EXPLAIN
    SQL> SELECT COUNT (*) FROM test_table WHERE TRUNC (created) = TRUNC (SYSDATE)
      2  /
      COUNT(*)                                                                     
             3                                                                     
    Execution Plan
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=9)            
       1    0   SORT (AGGREGATE)                                                   
       2    1     INDEX (RANGE SCAN) OF 'T_FBI' (NON-UNIQUE) (Cost=1 Card=         
              10 Bytes=90)                                                         
    SQL> SELECT COUNT (*) FROM test_table WHERE trunc(created) = TRUNC (SYSDATE)
      2  /
      COUNT(*)                                                                     
             3                                                                     
    Execution Plan
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=9)            
       1    0   SORT (AGGREGATE)                                                   
       2    1     INDEX (RANGE SCAN) OF 'T_FBI' (NON-UNIQUE) (Cost=1 Card=         
              10 Bytes=90)                                                

  • Using function based index causing connection to abort

    My problem is as below
    I m using oracle 8i data base
    I have a table Dummy with column col1 .
    I have created a function based index on col1
    Now i try to update the table dummy using this function based index (i.e)
    i run the following query
    update dummy set col2='new value' where col1=ltrim(col2,'0')
    now when i execute this statement it causes the connection to abort. It gives the error
    ERROR at line 1:
    ORA-03113: end-of-file on communication channel
    But if i run select query (i.e) select col2 from dummy where col1=ltrim(col2,'0')
    it executes sucessfully.
    Also if i wrap the ltrim over some other function it works (i.e.)
    update dummy set col2='new value' where col1=upper(ltrim(col2,'0'))
    Any thoughts or ideas on what can be the reason...
    plese let me know for any questions,clarifications..
    Thanks in advance...
    Balaji

    Balaji, what is the exact error message returned? Remember to always include all the error details so that the problem can be identified and diagnosed.
    If you mean you are getting an ORA-03113: end-of-file on communication channel, this means that the Oracle Server Process that serviced your client session, crashed.
    In that case you need to refer to the alert log file on the database instance to see the server-side error message that resulted (often an ORA-0600 internal error) and the name of the trace file that was created at a result.
    You also failed to specify the exact Oracle 8i version you are using. Make sure you're on the very last patch set released for 8i - that should be 8.1.7.4 as far as I recall.

  • 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 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?...

Maybe you are looking for

  • Two delivery documents for a single schedule line of scheduling agreement

    Hi experts, i have a query, client needs the information of each schedule line delivery details. if all the quantiry in a schedule line is delivered in single delivery ,i can get the ref. from delivery header,,item details table. if i need to deliver

  • SetMedia problem with MediaPlayback - external MP3s

    I'm using the MediaPlayback component to play an external MP3 file, and it's working fine, EXCEPT that when it first loads it plays the first part of the clip for a split second, then stops and re-plays it -- regardless of the autoPlay settings that

  • Why won't downloaded movies play?

    The television series are safe but the movies won't convert.  I've changed Quicktime to Quicktime 7.6 but they won't play...

  • Lightroom 1.1 Slideshow Issues

    Hello, When I click the "play" arrow, or "Impromptu" key from the top tool bar, or "Play All" icon from the right hand of the screen, or any other attempt to get my slideshow to play, all I get is a black screen. I hit "escape", and it immediately go

  • CS4 keeps Crashing within seconds....WHY?!

    Every time I open a file, or import an xfl Flash crashes in 5 seconds. This started recently. I have tried different files, I have tried reinstalling and  the same thing keeps happening. Any solution to this?