Низька продуктивність при використанні просторових індексів у MySQL


13

Повторіть запитання, задане на Stack Overflow, коли було запропоновано, це буде кращим форумом.

Я намагаюся трохи експериментувати над тим, щоб натиснути набір даних, який не є геопросторовим, але він цілком відповідає, і я вважаю результати дещо неспокійними. Набір даних є геномними даними, наприклад, Геном людини, де ми маємо область ДНК, де такі елементи, як гени, займають конкретні координати початку та зупинки (наша вісь X). У нас є кілька областей ДНК (хромосом), які займають вісь Y. Мета полягає в тому, щоб повернути всі елементи, які перетинають дві координати X вздовж однієї координати Y, наприклад LineString (START 1, END 2).

Теорія здалася здоровою, тому я втілив її в існуючий проект геному на MySQL і створив структуру таблиці на зразок:

CREATE TABLE `spatial_feature` (
  `spatial_feature_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `external_id` int(10) unsigned NOT NULL,
  `external_type` int(3) unsigned NOT NULL,
  `location` geometry NOT NULL,
  PRIMARY KEY (`spatial_feature_id`),
  SPATIAL KEY `sf_location_idx` (`location`)
) ENGINE=MyISAM;

external_idпредставляє ідентифікатор сутності, яку ми закодували в цю таблицю, і external_typeкодує джерело цього. Все виглядало добре, і я зафіксував деякі попередні дані (30 000 рядків), які, здавалося, спрацювали добре. Коли цей показник збільшився за останні 3 мільйони міток рядка, MySQL відмовився від використання просторового індексу і був повільнішим, коли його змусили використовувати (40 секунд проти 5 секунд при повному скануванні таблиці). Коли було додано більше даних, почали використовувати індекс, але покарання за ефективність зберігається. Вимкнення індексу знизило запит до 8 секунд. Запит, який я використовую, виглядає так:

select count(*)
from spatial_feature
where MBRIntersects(GeomFromText('LineString(7420023 1, 7420023 1)'), location);

Дані, що впадають у це, дуже щільні за розмірами Y (подумайте про це, як ви записали положення кожної будівлі, телефонної скриньки, поштової скриньки та голуба на дуже довгій дорозі). Я робив тести, як R-індекси поводяться з цими даними на Java, а також інші в цій галузі успішно застосовували їх до форматів плоских файлів. Однак ніхто не застосовував їх до баз даних AFAIK, що є метою цього тесту.

Хтось там бачив подібну поведінку, додаючи велику кількість даних до просторової моделі, яка не дуже розрізнена по певній осі? Проблема зберігається, якщо я скасую використання координат. Я виконую наступні налаштування, якщо це є причиною

  • MacOS 10.6.6
  • MySQL 5.1.46

Відповіді:


5

MySQL, як PostGIS, зберігає дані просторового індексу в структурі R-дерева, щоб він міг швидко знаходити речі. R-дерево, як і B-дерево, організоване таким чином, що воно оптимізоване для отримання лише невеликої частки загальних даних у таблиці. Насправді швидше ігнорувати індекс для запитів, яким потрібно прочитати великий розділ таблиці, щоб повернути дані або виконати величезне з'єднання, класичний випадок, який спричиняє багато форумів бази даних [плакатів], які скаржаться на запит, який повертає половину їх таблиця "не використовуючи новий індекс, який вони тільки що створили."

З http://rickonrails.wordpress.com/2009/03/30/big-ole-mysql-spatial-table-optimization-tricks/

Якщо ви можете вмістити всі дані таблиці в пам’ять, ваші показники хороші. Якщо / коли вам потрібно почати робити читання диска, продуктивність швидко погіршується. Ви робили схеми використання пам'яті вашого екземпляра mysql для двох випадків: 30k рядків проти 3000k рядків?


Я думаю, це може бути ближче до питання. TBH його R-індекс я хочу; інші просторові математики - це приємний бонус, оскільки це доведеться робити в шарі API в старій системі. Я спробував трохи настроїти, але збільшення ключових буферів не допомогло (інші буфери тут не допоможуть, як буфер таблиці, оскільки це запит на 1 таблицю на моєму персональному сервері). Дивно, що MySQL забиває мою машину під землю, коли запити виконуються (100% під час виконання запиту). Це сказало, що робить сканування повного столу, тож, можливо, це не так дивно
andeyatz

5

Щось має бути не так з вашою установкою mysql або налаштуваннями .ini. Щойно тестував геопросторовий індекс на моєму старому mac (10.6.8 / MySQL 5.2). Ця конфігурація схожа на вашу, і я протестував великий дамп геодета ( 9 мільйонів записів ). Я зробив цей запит:

SET @radius = 30;
SET @center = GeomFromText('POINT(51.51359 7.465425)');
SET @r = @radius/69.1;
SET @bbox = CONCAT('POLYGON((', 
  X(@center) - @r, ' ', Y(@center) - @r, ',', 
  X(@center) + @r, ' ', Y(@center) - @r, ',', 
  X(@center) + @r, ' ', Y(@center) + @r, ',', 
  X(@center) - @r, ' ', Y(@center) + @r, ',', 
  X(@center) - @r, ' ', Y(@center) - @r, '))' 
);

SELECT geonameid, SQRT(POW( ABS( X(point) - X(@center)), 2) + POW( ABS(Y(point) - Y(@center)), 2 ))*69.1 
AS distance
FROM TABLENAME AS root
WHERE Intersects( point, GeomFromText(@bbox) ) 
AND SQRT(POW( ABS( X(point) - X(@center)), 2) + POW( ABS(Y(point) - Y(@center)), 2 )) < @r 
ORDER BY distance; 

Минуло всього 0,0336 сек.

Я використовую вищезазначений запит, наприклад, для порівняння таблиць, де таблиця, з якої походять лише значення lat / lng для @center, має звичайний INDEX від city_latitude / city_longitude та 9-12 Міо. таблиця від geonames.org має геопросторовий індекс.

І я просто хотів додати, що коли хтось вставляє великі дані в таблицю, може бути більш ефективним додавати індекс після INSERT. Якщо ні, це займе більше часу для кожного доданого ряду ... [але це не важливо]


Нічого, це справді добре. Тепер я не впевнений, що я робив неправильно у власних тестах. Одне, що може спричинити проблему, - це характер моїх наборів даних порівняно з більш традиційними наборами геопросторових даних. Це сказав, що я просто здогадуюсь і не маю підстав для цього. Чудово бачити, що вам не потрібно змушувати індекс в пам'яті, щоб отримати швидкість.
andeyatz

Пункт WHERE з радіусом може відфільтрувати хорошу частину таблиці з використання індексу.
tmarthal

2

Чи думали ви розбити його на два 1D стовпці замість одного 2D стовпця?

Оптимізатор може задушитись усіма подібними даними та мати два стовпці з більшою різноманітністю.

Що ви також можете перевірити - це порядок перевірки предметів. У мене виникла проблема в Oracle Spatial, де я шукав прізвище та фільтр IN_REGION. Oracle вирішив, що найшвидший спосіб - використовувати прізвище, а потім зробити перевірку регіону. Дозвольте вам сказати, що в регіоні перевірка всіх Робінзонів у Клівленді відбувається повільно . Пам’ятаю, мені довелося передавати специфічний аргумент Oracle, щоб змусити його спочатку використовувати просторовий індекс.


На жаль, 1 вимір набагато менш населений, ніж інший. Для цього в геномі людини геном людини має 24 унікальні хромосоми (22 пари та дві статеві хромосоми) разом із пакетами даних, зібраними на різні рівні. Що означає, якщо ви зіставляєте елементи до базового випадку використання, який становить лише 24 унікальних ідентифікатора в одному вимірі. Початкова надія полягала в тому, що індекс R-дерева міг би виконати не тільки більш ефективну перевірку діапазону перекриття, але й диференціювати ці регіони в одному запиті.
andeyatz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.