Низкая производительность при использовании пространственных индексов в MySQL - PullRequest
9 голосов
/ 21 января 2011

Я пытаюсь провести небольшой эксперимент по передаче набора данных, который не является геопространственным, но подходит ему достаточно хорошо, и результаты меня несколько тревожат.Набор данных - это данные генома, например, человеческий геном, где у нас есть область ДНК, где такие элементы, как гены, занимают определенные начальные и конечные координаты (наша ось 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

Справка!

Также добавлен план объяснения в

+----+-------------+-----------------+------+-----------------+------+---------+------+---------+----------+-------------+
| id | select_type | table           | type | possible_keys   | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+-----------------+------+-----------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | spatial_feature | ALL  | sf_location_idx | NULL | NULL    | NULL | 3636060 |    33.33 | Using where |
+----+-------------+-----------------+------+-----------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

Переписанный SQL выглядит следующим образом

select count(0) AS `count(*)` from `arabidopsis_thaliana_core_7_60_9`.`spatial_feature` where intersects(geometryfromtext('LineString(7420023 1, 7420023 1)'),`arabidopsis_thaliana_core_7_60_9`.`spatial_feature`.`location`)

Все еще не подчеркивая, почему производительность этого запроса настолько низкая

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

Какова мораль этой истории?R-индексы в MySQL имеют довольно низкую производительность, пока они не находятся в памяти, а затем они имеют отличную производительность.Не очень хорошее решение для того, что я хотел сделать с ними, но все же оно предоставляет интересный взгляд на MySQL.

Спасибо за помощь всем людям.

Ответы [ 4 ]

1 голос
/ 13 мая 2014

Из плана EXPLAIN мы видим, что, хотя для запроса может использоваться пространственное значение (столбец 'возможные_ключи'), оно не используется (NULL в столбце 'ключевой').Я не уверен, почему он не выбран автоматически, но вы можете явно указать MySql использовать индекс, указав его в запросе с помощью предложения 'force index':

select count(*)
from spatial_feature 
force index (sf_location_idx) --  <== this is the 'force index' clause
where MBRIntersects(GeomFromText('LineString(7420023 1, 7420023 1)'), location);
0 голосов
/ 11 ноября 2014

Вы уверены, что реляционная база данных - это путь?Если бы я был вами, я бы посмотрел на отправку ваших наборов данных в Solr или Elastic Search (возможно, для хранения основных наборов данных в другом месте).Эти механизмы созданы для индексации, вы заметите разницу во времени отклика.

0 голосов
/ 19 июня 2012

У меня есть степень в области генетики, и я программист, вам не нужно использовать X и Y, так как ваша номенклатура будет слишком капризной ... вам нужен старт и остановка позиция (не «ось») и хромосома номер. Вы индексируете сначала по номеру хромосомы, затем по позиции, а затем по индексу, а затем по хромосоме. (Вопрос: Вы имеете дело с эукариотами или хромосомами, которые могут иметь две рамки для чтения?)

EG: (где "x" = положение и "y" = хромосома)

CREATE INDEX spatial_index_1 ON spatial_feature(chromosome, position);
CREATE INDEX spatial_index_2 ON spatial_feature(position, chromosome);

Между прочим, хромосомы - это очень длинные цепочки (точно так же как данные), которые вы можете (чтобы ускорить процесс, сбросьте их, например, капли (то есть кодирующие гены и ненужную ДНК)

0 голосов
/ 07 апреля 2011

Цель состоит в том, чтобы вернуть все предметы, которые пересекают два X координаты вдоль одного Y координата

Рассматривали ли вы использование индекса с несколькими полями? Как:

CREATE INDEX spacial_search ON spatial_feature(y, x)

Если вы работаете с ограниченным набором y значений, это путь к.

...