ORA-13249: SDO_NN не может быть оценен без использования индекса

#oracle #oracle11g #oracle10g #oracle-spatial

#Oracle #оракул11g #оракул10g #оракул-пространственный

Вопрос:

Я получаю ошибку при запуске следующего Sql-скрипта в ORACLE

 SELECT D.ID FROM DOOR D JOIN STREET S ON (S.ID=D.STREET_ID) WHERE  SDO_NN(D.LOCATION,SDO_UTIL.FROM_WKTGEOMETRY('POINT (11112.0111 321314.2222)'),'sdo_num_res=6') = 'TRUE' or  S.ID IN (17);  

но когда я изменяю «или» на «и» или удаляю «или S.ID В (17)» Я не получаю ошибок.

 SELECT D.ID FROM DOOR D JOIN STREET S ON (S.ID=D.STREET_ID) WHERE  SDO_NN(D.LOCATION,SDO_UTIL.FROM_WKTGEOMETRY('POINT (11112.0111 321314.2222)'),'sdo_num_res=6') = 'TRUE' and  S.ID IN (17);  

Тип поля местоположения в таблице ДВЕРЕЙMDSYS.SDO_GEOMETRY

и

Тип поля идентификатора в таблице УЛИЦНОМЕР

Я хочу, чтобы первый SQL работал. кто-нибудь может помочь с решением?

Ответ №1:

Намек принесет какую-нибудь пользу?

 SELECT /*  LEADING(d) USE_NL(d s) INDEX s spatial_index) */  D.ID  FROM DOOR D JOIN STREET S ON (S.ID = D.STREET_ID)  WHERE SDO_NN (  D.LOCATION,  SDO_UTIL.FROM_WKTGEOMETRY ('POINT (11112.0111 321314.2222)'),  'sdo_num_res=6') =  'TRUE'  AND S.ID IN (17);  

Комментарии:

1. запрос все еще не работал

Ответ №2:

Проблема здесь заключается в том, что оператор SDO_NN (в отличие от операторов SDO_RELATE или SDO_WITHIN_DISTANCE) может быть решен только с помощью пространственного индекса.

При первом запросе фактический фильтр для выбора из таблицы DOOR не применяется, поэтому оптимизатор запросов, естественно, использует пространственный индекс.

Со вторым запросом вы ограничиваете таблицу ДВЕРЕЙ только теми строками (дверями) для данной улицы (STREET.ID=17). Это заставляет оптимизатор выбирать индекс, который применяет этот фильтр (возможно, индекс на УЛИЦЕ.STREET_ID.

Или vs и создает совсем другой запрос и совсем другой результат. С помощью или вы запрашиваете 6 ближайших дверей к выбранной точке, с любой улицы все двери на улице 17, независимо от близости.

С и вы спрашиваете только о 6 ближайших дверях на улице 17. Что имеет гораздо больше смысла, чем первый синтаксис.

Чтобы это сработало в вашем случае, вам нужно использовать подсказку, чтобы указать оптимизатору использовать пространственный индекс вместо индекса DOOR.STREET_ID:

 SELECT /*  INDEX (d lt;spatial index namegt;) */ D.ID FROM DOOR D JOIN STREET S ON (S.ID=D.STREET_ID) WHERE SDO_NN(D.LOCATION,SDO_UTIL.FROM_WKTGEOMETRY('POINT (11112.0111 321314.2222)'),'sdo_num_res=6') = 'TRUE' AND S.ID IN (17);  

Обратите внимание на синтаксис подсказки: d относится к псевдониму, который ссылается на таблицу ДВЕРЕЙ, так как именно на ней вы выполняете пространственную фильтрацию. lt;spatial index namegt; это имя пространственного индекса, который вы определили в таблице DOOR (не строка «spatial_index».

Подсказки имеют «хрупкий» синтаксис: если вы сделаете какую-либо ошибку, подсказка будет просто проигнорирована. Кроме того, они не являются приказами оптимизатору: это просто предложения. Если оптимизатор обнаружит, что подсказку невозможно применить (например, вы запрашиваете несуществующий индекс), он также проигнорирует ее.

Один из способов подтвердить, что подсказки были приняты и использованы оптимизатором, — это просмотреть созданный им план запроса. Если вы используете sqlplus или sqlcl, вы можете использовать EXPLAIN PLAN команду, которая покажет вам план, фактически не выполняя инструкцию. Если вы используете SQLDeveloper, в нем есть специальные кнопки для отображения планов запросов.

ИЗМЕНИТЬ: INDEX Подсказки может быть недостаточно. Возможно, оптимизатору также нужно рассказать, как реализовать объединение, как указал @littlefoot. Так что вам также могут понадобиться LEADING USE_NL подсказки и. Но сначала попробуйте использовать только INDEX подсказку.

Комментарии:

1. Я попробовал то, что ты сказал, но это не сработало.

2. Намеки бывает трудно приручить. Вы уверены, что используете правильное имя пространственного индекса в подсказке ?

3. Можно ли поделиться данными и таблицами, которые вы используете, или, по крайней мере, их подмножеством ?