2009-06-25 6 views
1

Oracle 10g의 (공간) 쿼리는 매개 변수 값에 따라 다른 실행 계획을 얻습니다. 그리고 슬프게도 오라클은 계획 중 하나를 전혀 실행할 수 없으므로 오류가 발생합니다. 값을 변경 (282 미만에서 284 이하)하거나 연산자 (= <에서)로 변경하면 결과가 나타납니다. 계획이 다른 이유는 무엇입니까? 왜 oracle은 실행 불가능한 계획을 선택합니까? 오라클이 실행 가능한 실행 계획을 선택하게하려면 어떻게해야합니까?Oracle Spatial에서 "실행 가능한"실행 계획을 선택하도록하는 방법

쿼리 :

select nn.poi_id as id 
    from 
    poi p, 
    (select pl.poi_id 
    from 
     poi_loc pl, 
     poi_loc pl2 
    where 
    pl2.poi_id = 769 
    and 
    pl.poi_id<>769 
    and 
    sdo_nn(pl.wgs84, pl2.wgs84)='TRUE' 
) nn 
    where 
    cat_id = 282 
    and 
    p.id = nn.poi_id 
     and 
    rownum<7; 

주기 오류 : 실행하지 않습니다

ORA-13249: SDO_NN cannot be evaluated without using index 
ORA-06512: at "MDSYS.MD", line 1723 
ORA-06512: at "MDSYS.MDERR", line 17 
ORA-06512: at "MDSYS.PRVT_IDX", line 22 

계획 : 실행하고 결과

| Id | Operation      | Name     | Rows | Bytes | Cost (%CPU)| Time  | 

---------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |       |  6 | 1890 | 106 (1)| 00:00:02 | 
|* 1 | COUNT STOPKEY     |       |  |  |   |   | 
|* 2 | HASH JOIN     |       |  6 | 1890 | 106 (1)| 00:00:02 | 
|* 3 | TABLE ACCESS BY INDEX ROWID | POI      | 573 | 5157 | 41 (0)| 00:00:01 | 
|* 4 |  INDEX RANGE SCAN   | POI_CAT_ID_IDX   | 573 |  |  2 (0)| 00:00:01 | 
| 5 | NESTED LOOPS    |       | 301 | 92106 | 65 (2)| 00:00:01 | 
| 6 |  TABLE ACCESS BY INDEX ROWID| POI_LOC     |  1 | 153 |  2 (0)| 00:00:01 | 
|* 7 |  INDEX RANGE SCAN   | POI_LOC_POI_ID_IDX  |  1 |  |  1 (0)| 00:00:01 | 
|* 8 |  TABLE ACCESS BY INDEX ROWID| POI_LOC     | 302 | 46206 | 65 (2)| 00:00:01 | 
|* 9 |  DOMAIN INDEX    | POI_LOC_SP_IDX   |  |  |   |   | 
Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter(ROWNUM<7) 
    2 - access("P"."ID"="PL"."POI_ID") 
    3 - filter("P"."ID"<>769) 
    4 - access("CAT_ID"=284) 
    7 - access("PL2"."POI_ID"=769) 
    8 - filter("PL"."POI_ID"<>769) 
    9 - access("MDSYS"."SDO_NN"("PL"."WGS84","PL2"."WGS84")='TRUE') 
에게 제공

| Id | Operation      | Name     | Rows | Bytes | Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |       |  1 | 315 |  6 (0)| 00:00:01 | 
|* 1 | COUNT STOPKEY     |       |  |  |   |   | 
|* 2 | TABLE ACCESS BY INDEX ROWID | POI_LOC     |  1 | 153 |  2 (0)| 00:00:01 | 
| 3 | NESTED LOOPS     |       |  1 | 315 |  6 (0)| 00:00:01 | 
| 4 |  NESTED LOOPS    |       |  1 | 162 |  4 (0)| 00:00:01 | 
|* 5 |  TABLE ACCESS BY INDEX ROWID| POI      |  1 |  9 |  2 (0)| 00:00:01 | 
|* 6 |  INDEX RANGE SCAN   | POI_CAT_ID_IDX   |  1 |  |  1 (0)| 00:00:01 | 
| 7 |  TABLE ACCESS BY INDEX ROWID| POI_LOC     |  1 | 153 |  2 (0)| 00:00:01 | 
|* 8 |  INDEX RANGE SCAN   | POI_LOC_POI_ID_IDX  |  1 |  |  1 (0)| 00:00:01 | 
|* 9 |  INDEX RANGE SCAN   | POI_LOC_POI_ID_IDX  |  1 |  |  1 (0)| 00:00:01 | 
----------------------------------------------------------------------------------------------------------- 

    1 - filter(ROWNUM<7) 
    2 - filter("MDSYS"."SDO_NN"("PL"."WGS84","PL2"."WGS84")='TRUE') 
    5 - filter("P"."ID"<>769) 
    6 - access("CAT_ID"=282) 
    8 - access("P"."ID"="PL"."POI_ID") 
     filter("PL"."POI_ID"<>769) 
    9 - access("PL2"."POI_ID"=769) 

계획

답변

0
당신은 단지 힌트에게 적절한 방법을 쓸 필요가

:

select nn.poi_id as id 
    from 
    poi p, 
    (select /*+ index (pl POI_LOC_SP_IDX) */ pl.poi_id 
    from 
     poi_loc pl, 
     poi_loc pl2 
    where 
    pl2.poi_id = 769 
    and 
    pl.poi_id<>769 
    and 
    sdo_nn(pl.wgs84, pl2.wgs84)='TRUE' 
) nn 
    where 
    cat_id = 282 
    and 
    p.id = nn.poi_id 
    and rownum<7; 

오류에 대한 이유는 (비 공간) 다른 술어 색인 것을 생각하기 때문에 최적화가 공간 인덱스를 사용하지 않는 선택이다 더 선택적입니다. 공간 쿼리가 작동하려면 공간 인덱스가 있어야하지만 옵티마이 저는 공간 쿼리를 사용하지 않을 수도 있습니다. 이것은 SDO_RELATE와 SDO_ANYINTERACT 연산자에서는 잘 동작하지만 SDO_NN에서는 제대로 동작하지 않습니다.

0

어쨌든 wgs84의 색인을 추가해야합니다.

실마리가 없다면 DBA에게 문의하십시오.

일부 정보는 http://download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_index_query.htm#i1000846을 참조하십시오.

+0

색인이 이미 있습니다. 오라클이 매번 그것을 사용하도록 어떻게 할 수 있습니까? – Riivo

+0

인덱스가 이미있는 경우 계획이 오래되었을 수 있습니다. pl/sql 인 경우 다시 컴파일하십시오. 그렇지 않으면 dbms_stats 팩으로 통계를 업데이트하십시오. 이러한 모든 작업을 수행 한 후에도 여전히 작동하지 않으면 옵티 마이저 힌트를 사용하십시오. ID/BLUE blar blar blar –

+0

계획이 오래되었다고 생각하지 않습니다. SELECT/* + INDEX (YOU_INDEX_NAME) */nn.poi_id as id . 그것의 평범한 SQL. 값에 따라 때때로 POI_LOC_SP_IDX를 사용하는 계획을 선택하고 쿼리가 올바르게 작동합니다. 이 힌트는이 경우에도 도움이되지 않습니다. – Riivo