2014-10-28 2 views
0

비용이 많이 드는 (Oracle) 술어에 함수 기반 인덱스를 만들려고합니다. 연방 수사 국 (FBI)함수 기반 인덱스를 생성 할 때 누락 괄호 오류가 발생했습니다.

SELECT * FROM A4ORDERS WHERE TRIM(TO_CHAR(time_id, 'Month')) in ('December'); 

만들기 :

나는 12 월의 달의 값을 다시 가져 오는 A4ORDERS 테이블의 TIME_ID 컬럼에 인덱스를 생성 할

CREATE INDEX TIME_FIDX ON A4ORDERS(TRIM(TO_CHAR(time_id, 'Month')) in ('December')); 

나는 "누락 수 오른쪽 괄호 "오류와 이유를 알 수없는 이유는 무엇입니까? 당신이 제공 할 수있는 모든 지침을 주시면 감사하겠습니다. 그 아래 알렉스 풀의 응답에서

솔루션 일 :

CREATE INDEX TIME_FIDX ON A4ORDERS(TRIM(TO_CHAR(time_id, 'Month'))); 

을하지만, 또한 당신이 더 간단 비트 수 :

CREATE INDEX TIME_FIDX ON A4ORDERS (TRIM(TO_CHAR(time_id, 'Month'))); 
+1

색인은 "값을 되돌려 놓지 않습니다". 12 월의 값에 대해서만 색인을 원하십니까? –

+0

예. 어떻게해야합니까? – ShoSom

+0

나는 당신이 성취하려는 것을 설명해야한다고 생각합니다. 예를 들어 어떤 쿼리를 최적화하려고합니까? –

답변

2

create index 문에는 in ('December') 부분이 없어야합니다.이 부분은 쿼리에만 속합니다. ... 그 인덱스가 쿼리에 의해

CREATE INDEX TIME_FIDX ON A4ORDERS (TRIM(TO_CHAR(time_id, 'Month'))); 

을 사용할 수 있습니다 : 당신이 인덱스를 작성하는 경우
EXPLAIN PLAN FOR 
SELECT * FROM A4ORDERS WHERE TRIM(TO_CHAR(time_id, 'Month')) in ('December'); 

SELECT plan_table_output FROM TABLE (dbms_xplan.display()); 

----------------------------------------------------------------------------------------- 
| Id | Operation     | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |   |  1 | 29 |  2 (0)| 00:00:01 | 
| 1 | TABLE ACCESS BY INDEX ROWID| A4ORDERS |  1 | 29 |  2 (0)| 00:00:01 | 
|* 2 | INDEX RANGE SCAN   | TIME_FIDX |  1 |  |  1 (0)| 00:00:01 | 
----------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id):          
---------------------------------------------------          

    2 - access(TRIM(TO_CHAR(INTERNAL_FUNCTION("TIME_ID"),'Month'))='December')   

그래서 당신은 TIME_FIDX를 사용중인 것입니다 계획에서 볼 수 있습니다. 중요한 성능 향상을 가져다 줄 수 있는지 여부는 물론 파악되어야하며 옵티마이 저는이 옵션이 충분히 선택적인 것은 아니라고 판단 할 수 있습니다.

'월'은 NLS에 민감합니다. 달 번호를 사용하거나 TO_CHAR 호출에서 NLS_DATE_LANGUAGE를 지정하는 것이 더 안전 할 수 있지만 일관되게 수행해야합니다. 이는 숫자가 조금 더 쉬울 것입니다. 또한 인덱싱 된 가상 열을 만들 수도 있습니다.

+0

와우. 이것은 실제로 내가 원했던 것을 정확히 되찾았습니다. 고맙습니다. – ShoSom

+0

@ShoSom - 기본적으로 모든 달 이름은 가장 긴 이름의 길이 인 9 월 (영어 데이터 언어 사용)까지 공백으로 채워지기 때문에 'TRIM'이 필요합니다. 트림이 없으면 색인 된 값은''December ''이고 뒤에 공백이 있습니다. [FM 수정 자] (http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements004.htm#SQLRF00216), 즉'fmMonth', 처음에는 패딩 된 값을 갖지 않으려면자를 필요가 없습니다. 그러나 쿼리는 인덱스와 정확히 동일해야합니다. 숫자가 더 간단 해지는 또 다른 이유는 ... –

+0

많은 의견이 있습니다. 자세한 의견을 보내 주셔서 감사합니다. – ShoSom

2

당신이 사용할 수있는

CREATE INDEX TIME_FIDX ON A4ORDERS(TO_CHAR(time_id, 'mm')); 

및 쓰기 SQL :

SELECT * FROM A4ORDERS WHERE TO_CHAR(time_id, 'mm') in ('12'); 

그러나 문제 (해결 방법, SQL 쿼리, 계획 등)에 대한 추가 정보를 제공하면 도움을받을 수 있습니다.

관련 문제