Syntax for existing function-based index
Hi:
I am on 10.2.0.3.
Listed below is the list of indexes and index columns on one of the tables. Aparantly one of the columns (SYS_NC00220$ ) is in reality a function-based index.
Anybody knows how to get SQL syntax for this index? TIA.
INDEX_NAME UNIQUENES COLUMN_NAME COLUMN_POSITION
PS0BI_HDR NONUNIQUE BILL_TO_CUST_ID 1
PS0BI_HDR NONUNIQUE BUSINESS_UNIT 2
PS0BI_HDR NONUNIQUE SYS_NC00220$ 3
PS1BI_HDR NONUNIQUE BILL_STATUS 1
PS1BI_HDR NONUNIQUE BUSINESS_UNIT 2
PS1BI_HDR NONUNIQUE SYS_NC00220$ 3
PS2BI_HDR NONUNIQUE CONTRACT_NUM 1
PS2BI_HDR NONUNIQUE BUSINESS_UNIT 2
PS2BI_HDR NONUNIQUE SYS_NC00220$ 3
PSABI_HDR NONUNIQUE INVOICE 1
PSABI_HDR NONUNIQUE BILL_TO_CUST_ID 2
PSABI_HDR NONUNIQUE BUSINESS_UNIT 3
PSABI_HDR NONUNIQUE BILL_STATUS 4
PSBBI_HDR UNIQUE PROCESS_INSTANCE 1
PSBBI_HDR UNIQUE BUSINESS_UNIT 2
PSBBI_HDR UNIQUE INVOICE 3
PS_BI_HDR UNIQUE BUSINESS_UNIT 1
PS_BI_HDR UNIQUE SYS_NC00220$ 2
query user_ind_expressions and look for COLUMN_EXPRESSION.
this will give you expression.
Similar Messages
-
Why do we need query rewrite enabled for a function-based index?
Oracle 9i
========
I have searched a few sites but could not find any content on it. The question is why do we need to implement query rewrite enabled when we are trying out a function-based index?
Thanks in advance.You don't, that's a legacy requirement from the early days of function based indexes in Oracle 8i. Here's a quick example running under 9.2.0.6
drop table t1;
create table t1 as
select
from
all_objects
where
rownum <= 30000
create or replace function pl_func(i_vc varchar2)
return varchar2
deterministic
as
begin
return soundex(i_vc);
end;
-- set the worst case scenario
alter session set query_rewrite_enabled = false;
alter session set query_rewrite_integrity = enforced;
create index t1_i1 on t1(pl_func(object_name));
execute dbms_stats.gather_table_stats(user, 't1')
set autotrace traceonly explain
select
object_name
from t1
where pl_func(object_name) = 'T513'
set autotrace offResults (after set feedback off)
SQL> @temp
Execution Plan
Plan hash value: 1429545322
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 27 | 675 | 10 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 27 | 675 | 10 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_I1 | 27 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("TEST_USER"."PL_FUNC"("OBJECT_NAME")='T513')
SQL> spool offRegards
Jonathan Lewis
http://jonathanlewis.wordpress.com
http://www.jlcomp.demon.co.uk -
Where to find info on function based indexes
Hello,
Using Oracle 11.2, can someone tell me where I can find information about existing Function Based indexes in my database?
I want to shrink the unused space on a table, but there is a FB index that I have to drop in order to shrink the space.
Then, I need to recreate it after I shrink the space.
But how do I find out what functions the index is created to be used for?
I've already looked at dba_indexes, and dba_ind_expressions with no luck.
I see the index, but I don't see what the functions are that are being applied for the FB index.
Thanks in advance.Yes, this is why I'm also confused, which is what I pointed out in the first entry of this thread.
Notice here:
SQL> select index_name, index_type from dba_indexes where table_name = 'TQR1';
INDEX_NAME INDEX_TYPE
IDX$$_0FFD0001 NORMAL
IDX$$_211C0002 NORMAL
TQR1_C3 FUNCTION-BASED NORMAL
. . .Now, let's confirm another way....
select OWNER, INDEX_NAME, INDEX_TYPE, TABLE_OWNER, TABLE_NAME
from dba_indexes where index_name = 'TQR1_C3';
OWNER INDEX_NAME INDEX_TYPE TABLE_OWNER TABLE_NAME
TQ TQR1_C3 FUNCTION-BASED NORMAL TQ TQR1
1 row selected.Now, let's show the selection from dba_ind_expressions...
INDEX_OWNER INDEX_NAME TABLE_OWNER TABLE_NAME COLUMN_EXPRESSI COLUMN_POSITION
TQ TQR1_C3 TQ TQR1 "C3" 1I don't know the password for the TQ owner, so I'll have to wait until I can find that out before I can run DBMS_METADATA. -
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 -
Function Based Index MOD(column_name,8)
For a function based index (MOD(column_name,8), the query is not using it. Do anyone have a solution to it? The table is having millions of rows.
Oracle only uses indexes if the number of returned rows is less than (i think) 4%. In your case the number of rows is 12,5% so Oracle will never use this index unless you force it
-
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?
ChinniOne 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.KishoreOne 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 -
Why Segment shrink is not supported for tables with function-based indexes
As we all know , Segment shrink is not supported for tables with function-based indexes.
But i'm very confused .
Why Segment shrink is not supported for tables with function-based indexes ?? what's its essential?Creating a function based index creates a hidden virtual column (you'll see it if you query user_tab_cols) and once you index a virtual column you can no longer shrink the table:orcl> create table t1(c1 number,c2 as (c1 * 2)) segment creation immediate;
Table created.
orcl> alter table t1 enable row movement;
Table altered.
orcl>
orcl> alter table t1 shrink space;
Table altered.
orcl> create index i2 on t1(c2);
Index created.
orcl> alter table t1 shrink space;
alter table t1 shrink space
ERROR at line 1:
ORA-10631: SHRINK clause should not be specified for this object
orcl>so the issue is not with function based indexes per se, it is a level beneath that. Perhaps because the virtual column has no physical existance, when the row is moved there is no reason for Oracle to realize that an index needs updating? I haven't attempted to reverse engineer this, I would be interested to know if anyone else has. -
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?...
-
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. -
How to create function based index for TO_CHAR
i need to create a function based index for the function to_char.when i tried ,i got an error,"only pure function can be indexed".what the error really means, help me in creating the index to reduce my query cost.
It works fine on my database. version 9iR2
create index IDX_TO_CHAR on emp(to_char(hiredate,'YYYY-MM-DD HH24:MI:SS'));
explain plan for
select hiredate from emp where to_char(hiredate,'YYYY-MM-DD HH24:MI:SS')='1981-05-01 00:00:00';
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 1 | 8 | 2 (50)|
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 8 | 2 (50)|
|* 2 | INDEX RANGE SCAN | IDX_TO_CHAR | 1 | | 2 (50)|
Predicate Information (identified by operation id):
2 - access(TO_CHAR("EMP"."HIREDATE",'YYYY-MM-DD HH24:MI:SS')='1981-05-01 00
:00:00')Yours seem like a tuning issue, so why not give us your sql and execution plan and so on.
maybe there is other ways to tune your sql than creating a function based index? -
How to define error message for function based index violation?
Hi,
I am generating Forms 6i from Designer 6i. I have a function based index to enforce case insensitive name uniqueness. With check constraints I can specify constraint violation error messages that will be displayed in Forms at runtime if needed. How can I do this with function based index constraints?
Regards,
TamasOK, problem sorted.
You need to create a check constraint with the same name as the new index, but don't enable it. -
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 -
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
OliverHi,
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. -
Query Transformation in Function Based Index's Expression
Hi All,
I am having a wired issue with Function Based Indexes on Orcale 10.2.0.3 running on Solaris 5.9.
I have created two FBI on two tables using following syntax.
CREATE INDEX EQHUB.IDX_BBO_WRT_DES_FBI ON EQHUB.BBO_WARRANT_PRICING (CASE WHEN latest_version_flag = 'Y' THEN 1 ELSE NULL END);
CREATE INDEX EQHUB.IDX_BBO_DES_FBI ON EQHUB.BBO_DESCRIPTIVE_DATA (CASE WHEN latest_version_flag = 'Y' THEN 1 ELSE NULL END);
For the second command (IDX_BBO_DES_FBI), when i query DBA_IND_EXPRESSIONS view, i found that Oracle has done some kind of QUERY TRANSFORMATION (?) and converted
FBI expression to CASE "LATEST_VERSION_FLAG" WHEN 'Y' THEN 1 ELSE NULL END.At the same time,EXPRESSION on first index is not changed.
Now,my question is what has made transformation to occure only for second index.
I also found that inspite of highly SELECTIVE nature of both the indexes, only SECOND index is being used by CBO (for which trasnformation occured)
and IDX_BBO_WRT_DES_FBI is not being used(FTS is happening instead).
Query is using same expression for both the tables as
(CASE WHEN latest_version_flag = 'Y' THEN 1 ELSE NULL END)=1
INDEX_NAME TABLE_NAME COLUMN_EXPRESSION
IDX_BBO_WRT_DES_FBI BBO_WARRANT_PRICING CASE WHEN "LATEST_VERSION_FLAG"='Y' THEN 1 ELSE NULL END
IDX_BBO_DES_FBI BBO_DESCRIPTIVE_DATA CASE "LATEST_VERSION_FLAG" WHEN 'Y' THEN 1 ELSE NULL ENDI read that expression should be evaluated including CASE of characters and spaces in query.Is that true?
Appreciating responses in advance.Randolf.
It's a shame that I forgot to look into the full execution plan information to check how Oracle really handles my queries.
Look here(edited for clarity):
explain plan for
select /*+ case1 ordered use_nl(x, y) */ count(case c1
when '1' then 1
when '2' then 2
when '3' then 3
else 4
end) from
(select level from dual connect by level <= 300000) x,
(select
from t1
) y;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 | 5 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | NESTED LOOPS | | 3 | 6 | 5 (0)| 00:00:01 |
| 3 | VIEW | | 1 | | 2 (0)| 00:00:01 |
| 4 | CONNECT BY WITHOUT FILTERING| | | | | |
| 5 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | T1 | 3 | 6 | 3 (0)| 00:00:01 |
Column Projection Information (identified by operation id):
1 - (#keys=0) COUNT(CASE WHEN "T1"."C1"='1' THEN 1 WHEN "T1"."C1"='2' THEN
2 WHEN "T1"."C1"='3' THEN 3 ELSE 4 END )[22]
2 - (#keys=0) "T1"."C1"[CHARACTER,1]
4 - "DUAL".ROWID[ROWID,10], LEVEL[4]
5 - "DUAL".ROWID[ROWID,10]
6 - "T1"."C1"[CHARACTER,1]
32 rows selected.
explain plan for select /*+ case2 ordered use_nl(x, y) */ count(case
when c1 = '1' then 1
when c1 = '2' then 2
when c1 = '3' then 3
else 4
end) from
(select level from dual connect by level <= 300000) x,
(select
from t1
) y;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 | 5 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | NESTED LOOPS | | 3 | 6 | 5 (0)| 00:00:01 |
| 3 | VIEW | | 1 | | 2 (0)| 00:00:01 |
| 4 | CONNECT BY WITHOUT FILTERING| | | | | |
| 5 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | T1 | 3 | 6 | 3 (0)| 00:00:01 |
Column Projection Information (identified by operation id):
1 - (#keys=0) COUNT(CASE WHEN "T1"."C1"='1' THEN 1 WHEN "T1"."C1"='2' THEN
2 WHEN "T1"."C1"='3' THEN 3 ELSE 4 END )[22]
2 - (#keys=0) "T1"."C1"[CHARACTER,1]
4 - "DUAL".ROWID[ROWID,10], LEVEL[4]
5 - "DUAL".ROWID[ROWID,10]
6 - "T1"."C1"[CHARACTER,1]As you exactly mentioned, I was executing different SQL but actually same queries!
Thanks for pointing my flaws.
PS) OP, forgive me for bothering you with off-topic things. :)
================================
Dion Cho - Oracle Performance Storyteller
http://dioncho.wordpress.com (english)
http://ukja.tistory.com (korean)
================================
Edited by: Dion_Cho on Feb 10, 2009 5:45 AM
Typo
Maybe you are looking for
-
Crystal report Chose from List or drop down value in parameter from UDT
Hi Experts, I had face a issue while creating a report for my client in crystal report , I had create a report and in the parameter field I want to select the value from the chose from list or drop down value from the User define table. In parameter
-
I just bought an iPhone 5. My iPhone 4 has all my music on it, mail, mms, sms, notes, videos, photos and apps. How do I transfer the music etc to my new iPhone? - icloud? - homesharing?
-
My airport won't connect right away; I have to turn it off first for it to connect
When I'm connected to the WiFi at my house and then connect to WiFi somewhere else it says it's connected but doesn't work and I have to turn off the Airport first and then turn it on again for it to really connect.
-
IE 10 Will not update photo captions.
Hi I have updated to IE 10 BUT when I view photos from a web site the photos change but the captions do not. It worked with IE 9 and works with Firefox and Torch but not IE 10 this is a bit annoying when I am trying to vote for my favourite photo. Al
-
No sound on Skype, but everything else works perfe...
I can listen to music on my computer, listen to stuff on youtube, even tried Teamspeak3 + Ventrilo and both works. I just simply can't hear on Skype, the mic is working perfectly because other people can hear me. Skype isn't making any sound, I can't