ST_DWithin був швидшим у моєму тесті, ніж ST_Intersects. Це дивно, тим більше, що підготовлений алгоритм геометрії передбачає подібні випадки. Я думаю, є ймовірність, що це буде набагато швидше, ніж я показав тут.
Я зробив ще кілька тестів, і дві речі майже в 10 разів подвоїли швидкість. По-перше, я спробував на більш новому комп’ютері, але все ж цілком звичайний ноутбук, можливо, крім SATA3 ssd -диски.
Тоді запит нижче займав 18 секунд замість 62 секунд на старому ноутбуці. Далі я виявив, що раніше я абсолютно помилявся, коли писав, що індекс на таблиці таблиці не потрібен. З цим індексом на місці ST_Intersects поводився як очікувалося, і все стало дуже швидко. Я збільшив кількість балів у табличній точці до 1 мільйона балів та запиту:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct , t WHERE ST_Intersects(imported_ct.geom , t.geom);
працює за 72 секунди. Оскільки є 1249 полігонів, 1249000000 тестів робиться за 72 секунди. Це робить близько 17000000 тестів за секунду. Або тестування майже 14000 балів проти всіх багатокутників за секунду.
Після цього тесту ваші 400000000 балів до тестування повинні тривати близько 8 годин без проблем з розподілом навантаження на кілька ядер. PostGIS ніколи не припиняє мене вражати :-)
По-перше, для візуалізації результату ви можете додати геометрію точки до отриманої таблиці, відкрити її в QGIS, наприклад, та накреслити її унікальними значеннями в полі import_ct.
По-друге, так, ви також можете отримати точки, що виходять за межі будь-якого багатокутника, скориставшись правим (або лівим) з'єднанням так:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct right join t ON ST_Intersects(imported_ct.the_geom , t.geom);
Я зробив кілька тестів, щоб перевірити, чи здається це можливим PostGIS.
Спочатку щось я не розумію. У вас є два очки за ряд. Чи завжди обидві точки в одному полігоні? Тоді досить зробити розрахунки по одній з точок. Якщо вони можуть бути у двох різних многокутниках, вам знадобиться спосіб з'єднати один точковий ряд з двома багатокутниками.
З тестів це здається можливим, але вам може знадобитися креативне рішення для поширення навантаження на більш ніж один процесор-ядро.
Я тестував 4-річний ноутбук з двоядерним процесором centrino (я думаю, приблизно 2,2 ГГц), 2 Гб оперативної пам’яті. Якщо у вас є 48 BG RAM, я думаю, у вас є і набагато більше процесорної потужності.
Що я зробив, це створити таблицю випадкових точок із 100000 балів, як це:
CREATE TABLE t AS
WITH r AS
(SELECT ST_Extent(the_geom)::geometry ext FROM imported_ct)
SELECT ST_Point(x,y) AS geom FROM
(SELECT GENERATE_SERIES(1,100000)) s,
(SELECT ST_Xmin(ext)+(random()*(ST_Xmax(ext)-ST_Xmin(ext))) x, ST_Ymin(ext)+(random()*(ST_Ymax(ext)-ST_Ymin(ext))) y FROM r
) f;
Потім додайте gid на зразок:
ALTER TABLE t ADD COLUMN GID SERIAL;
Потім працює:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE ST_Dwithin(imported_ct.the_geom , t.geom,0);
займає приблизно 62 секунди (порівняйте ваш результат ArcGIS з однаковою кількістю балів). Результатом є таблиця, що з'єднує точки моєї таблиці t з gid в таблиці з переписом.
З цією швидкістю ви зробите 200 мільйонів балів приблизно за 34 години. Отже, якщо цього достатньо для перевірки однієї точки, мій старий ноутбук може це зробити з одним ядром.
Але якщо вам потрібно перевірити обидва пункти, це може бути складніше.
Тоді ви можете вручну розподілити навантаження на більше одного ядра, запустивши кілька сеансів проти db та запустивши різні запити.
У своєму прикладі з 50000 очок та двома процесорними ядрами я спробував:
CREATE TABLE t1 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid >50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
на одному db-сеансі одночасно із запуском:
CREATE TABLE t2 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid <=50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
на іншому db-сеансі.
Це зайняло близько 36 секунд, тому це трохи повільніше, ніж перший приклад, ймовірно, залежно від запису диска одночасно. Але оскільки одночасно працюють бітові сердечники, це не зайняло більше 36 секунд мого часу.
Для об'єднання таблиць t1 і t2 a спробували:
CREATE TABLE t3 AS
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;
використовуючи приблизно півсекунди.
Отже, при більш свіжому обладнанні та розподілі навантаження на багато ядер це абсолютно повинно бути можливим, навіть якщо реальний світ буде повільнішим, ніж тестовий випадок.
Можливо, варто відзначити, що приклад з Linux (Ubuntu). Використання Windows буде іншою історією. Але в мене працюють всі інші щоденні програми, тому ноутбук досить сильно завантажений від раніше. Тож, можливо, це може імітувати корпус Windows цілком добре, не відкриваючи нічого, крім pgadmin.