Какова система координат ваших данных? И самое главное, какой допуск вы установили в своих метаданных?
Некоторые другие комментарии:
1) Не используйте отношение с буферным подходом. Просто используйте дистанционный подход.
2) Вам не нужен цикл PL/SQL для такого рода запросов, просто используйте простой CTAS:
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c2.mi_prinx <> c1.mi_prinx;
3) Как написано, пары точек A и B, находящиеся в пределах 2 см, будут возвращены дважды: один раз как (A,B) и еще раз как (B,A). Чтобы избежать этого (и вернуть только один из случаев), напишите запрос следующим образом:
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c1.rowid < c2.rowid;
3) Обработка упомянутого вами количества точек (400000+) должна работать лучше с использованием метода SDO_JOIN, например:
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from table (
sdo_join (
'ORAHAN','GEOLOC',
'ORAHAN','GEOLOC',
'DISTANCE=2 UNIT=CM'
)
) j,
orahan c1,
orahan c2
where j.rowid1 < j.rowid2
and c1.rowid = j.rowid1
and c2.rowid = j.rowid2;
Это, вероятно, все еще потребует времени для обработки - в зависимости от мощности вашего сервера базы данных. Если у вас есть лицензии на Oracle Enterprise Edition и ваше оборудование имеет достаточную мощность (количество ядер), то параллелизм может сократить затраченное время.
4) Вы говорите, что используете Oracle 11g. Какая именно версия? Версия 11.2.0.4 — это конечная версия 11gR2. Все, что старше, больше не поддерживается. К настоящему времени вы действительно должны быть на 12cR1 (12.1.0.2). Основным преимуществом версии 12.1.0.2 в вашем случае является функция Vector Performance Accelerator, которая ускоряет ряд пространственных функций и операторов (только если у вас есть соответствующие лицензии Oracle Spatial — она недоступна с бесплатной функцией Oracle Locator).
======================================
Используя две точки в вашем примере. Рассчитаем расстояние:
select sdo_geom.sdo_distance(
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
0.005
) distance
from dual;
DISTANCE
----------
.01000197
1 row selected.
Заметьте, я не указываю SRID. Если предположить, что координаты выражены в метрах, то расстояние между ними действительно чуть больше 1 см.
======================================
Причина, по которой ваш исходный синтаксис не работает, как вы заметили, заключается в допуске, указанном вами для вызова SDO_BUFFER(). Вы передаете его как 0,5 (= 50 см), чтобы создать буфер с радиусом 0,02 (2 см). Эффект заключается в том, что полученный буфер эффективно растворяется в самой точке.
Например, при допуске 0,5:
select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.5) from dual;
Производит:
SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(521554.782, 4230983.08, NULL), NULL, NULL)
При допуске 0,005:
select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005) from dual;
Вы получаете правильный буфер:
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 2), SDO_ORDINATE_ARRAY(521554.782, 4230983.06, 521554.802, 4230983.08, 521554.782, 4230983.1, 521554.762, 4230983.08, 521554.782, 4230983.06))
И самая близкая точка теперь совпадает с этим буфером:
select sdo_geom.relate(
sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005),
'determine',
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
0.005
) relation
from dual;
RELATION
-------------------------
CONTAINS
1 row selected.
======================================
Теперь тот факт, что ваши данные не имеют надлежащего явного SRID, означает, что использование явных единиц измерения или поиска на основе расстояния не будет работать. Поскольку база данных не знает, в какой системе координат находятся ваши данные, она не знает, как определить, что расстояние между двумя точками меньше заданного числа см или метров. Все, что вы можете сделать, это предположить, что координаты указаны в метрах.
Поэтому в приведенных выше примерах замените 'DISTANCE=2 UNIT=CM'
на 'DISTANCE=0.02'
.
person
Albert Godfrind
schedule
31.07.2016