- Когда мне следует использовать составной индекс в базе данных?
- Каковы разветвления производительности при использовании составного индекса)?
- Почему я должен использовать составной индекс?
Например, у меня есть homes
таблица:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
PRIMARY KEY (`home_id`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
) ENGINE=InnoDB ;
Имеет ли смысл использовать составной индекс для обоих geolat
и geolng
, чтобы:
Заменяю:
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
с участием:
KEY `geolat_geolng` (`geolat`, `geolng`)
Если так:
- Зачем?
- Каковы последствия использования составного индекса для повышения производительности)?
ОБНОВИТЬ:
Поскольку многие люди заявляли, что это полностью зависит от выполняемых мной запросов, ниже приведен наиболее распространенный запрос:
SELECT * FROM homes
WHERE geolat BETWEEN ??? AND ???
AND geolng BETWEEN ??? AND ???
ОБНОВЛЕНИЕ 2:
Со следующей схемой базы данных:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`primary_photo_group_id` int(10) unsigned NOT NULL default '0',
`customer_id` bigint(20) unsigned NOT NULL,
`account_type_id` int(11) NOT NULL,
`address` varchar(128) collate utf8_unicode_ci NOT NULL,
`city` varchar(64) collate utf8_unicode_ci NOT NULL,
`state` varchar(2) collate utf8_unicode_ci NOT NULL,
`zip` mediumint(8) unsigned NOT NULL,
`price` mediumint(8) unsigned NOT NULL,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`num_of_beds` tinyint(3) unsigned NOT NULL,
`num_of_baths` decimal(3,1) unsigned NOT NULL,
`num_of_floors` tinyint(3) unsigned NOT NULL,
`description` text collate utf8_unicode_ci,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
`display_status` tinyint(1) NOT NULL,
`date_listed` timestamp NOT NULL default CURRENT_TIMESTAMP,
`contact_email` varchar(100) collate utf8_unicode_ci NOT NULL,
`contact_phone_number` varchar(15) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`home_id`),
KEY `customer_id` (`customer_id`),
KEY `city` (`city`),
KEY `num_of_beds` (`num_of_beds`),
KEY `num_of_baths` (`num_of_baths`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
KEY `account_type_id` (`account_type_id`),
KEY `display_status` (`display_status`),
KEY `sqft` (`sqft`),
KEY `price` (`price`),
KEY `primary_photo_group_id` (`primary_photo_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;
Используя следующий SQL:
EXPLAIN SELECT homes.home_id,
address,
city,
state,
zip,
price,
sqft,
year_built,
account_type_id,
num_of_beds,
num_of_baths,
geolat,
geolng,
photo_id,
photo_url_dir
FROM homes
LEFT OUTER JOIN home_photos ON homes.home_id = home_photos.home_id
AND homes.primary_photo_group_id = home_photos.home_photo_group_id
AND home_photos.home_photo_type_id = 2
WHERE homes.display_status = true
AND homes.geolat BETWEEN -100 AND 100
AND homes.geolng BETWEEN -100 AND 100
EXPLAIN возвращает:
id select_type table type possible_keys key key_len ref rows Extra
----------------------------------------------------------------------------------------------------------
1 SIMPLE homes ref geolat,geolng,display_status display_status 1 const 2 Using where
1 SIMPLE home_photos ref home_id,home_photo_type_id,home_photo_group_id home_photo_group_id 4 homes.primary_photo_group_id 4
Я не совсем понимаю, как читать команду EXPLAIN. Это хорошо или плохо. В настоящий момент я НЕ использую составной индекс для геолокации и геолокации. Должна ли я быть?
источник
WHERE geolat BETWEEN ??? AND ??? AND geolng BETWEEN ??? AND ???
. Он остановится после первого поля. Ответ из «Вопроса переполнения» объясняет, почему.Представьте, что у вас есть три следующих вопроса:
Запрос I:
Запрос II:
Запрос III:
Если у вас есть отдельный индекс для каждого столбца, все три запроса используют индексы. В MySQL, если у вас есть составной индекс (
geolat
,geolng
), только запрос I и запрос II (который использует первую часть составного индекса) используют индексы. В этом случае запрос III требует поиска по всей таблице.В индексах с несколькими столбцами разделе руководства « несколькими столбцами» четко объясняется, как работают индексы с несколькими столбцами, поэтому я не хочу повторно набирать руководство.
На странице справочного руководства MySQL :
Если вы используете разделенный индекс для столбцов geolat и geolng, у вас есть два разных индекса в вашей таблице, которые вы можете искать независимо.
Если вы используете составной индекс, у вас есть только один индекс для обоих столбцов:
RRN - относительный номер записи (для упрощения можно сказать ID). Первые два индекса генерируются отдельно, а третий - составной. Как вы можете видеть, вы можете выполнять поиск на основе геолокации на составном, поскольку он проиндексирован геолатом, однако можно искать по геолату или "геолату И геолжингу" (поскольку геоланг является индексом второго уровня).
Также ознакомьтесь с разделом руководства, как MySQL использует индексы .
источник
BETWEEN
), никакие другие поля индекса не рассматриваются! Так что сводный индекс ничем не лучше.Может быть неправильное представление о том, что делает составной индекс. Многие думают, что составной индекс можно использовать для оптимизации поискового запроса, если
where
предложение охватывает индексированные столбцы, в вашем случаеgeolat
иgeolng
. Давайте копнем глубже:Я считаю, что ваши данные о координатах домов будут случайными десятичными знаками как таковые:
Поскольку
geolat
иgeolng
ценности почти не повторяются. Составной индекс наgeolat
иgeolng
будет выглядеть примерно так:Поэтому второй столбец сводного индекса в принципе бесполезен ! Скорость вашего запроса с составным индексом, вероятно, будет аналогична скорости индекса только для
geolat
столбца.Как упоминал Уилл, MySQL обеспечивает поддержку пространственного расширения . Пространственная точка хранится в одном столбце вместо двух отдельных
lat
lng
столбцов. К такому столбцу можно применить пространственный индекс. Однако, исходя из моего личного опыта, эффективность можно переоценить. Возможно, пространственный индекс не решает двумерную проблему, а просто ускоряет поиск с использованием R-деревьев с квадратичным разбиением .Компромисс заключается в том, что пространственная точка потребляет гораздо больше памяти, поскольку для хранения координат в ней используются восьмибайтовые числа с двойной точностью. Поправь меня, если я ошибаюсь.
источник
Составные индексы очень эффективны, поскольку они:
ОБЕСПЕЧЕНИЕ ЦЕЛОСТНОСТИ СТРУКТУРЫ
Составные индексы - это не просто еще один тип индекса; они могут предоставить НЕОБХОДИмую структуру для таблицы, обеспечивая целостность в качестве первичного ключа.
Mysql Innodb поддерживает кластеризацию, и следующий пример показывает, почему может потребоваться составной индекс.
Для создания таблиц друзей (например, для социальной сети) нам понадобятся 2 столбца:
user_id, friend_id
.Структура стола
По сути, первичный ключ (PK) уникален, и, создав составной PK, Innodb автоматически проверяет отсутствие дубликатов
user_id, friend_id
при добавлении новой записи. Это ожидаемое поведение, поскольку ни у одного пользователя не должно быть более 1 записи (связи отношения) сfriend_id = 2
.Без составного PK мы можем создать эту схему, используя суррогатный ключ:
Теперь, когда добавляется новая запись, нам нужно будет проверить, что предыдущая запись с комбинацией
user_id, friend_id
еще не существует.Таким образом, составной индекс может обеспечить целостность структуры.
ВКЛЮЧИТЬ СОРТИРОВКУ ПО ФИЛЬТРОВАННОМУ ИДЕНТИФИКАТОРУ
Очень часто набор записей сортируется по времени публикации (метка времени или дата-время). Обычно это означает публикацию по заданному идентификатору. Вот пример
Таблица User_Wall_Posts (подумайте, если посты на стене Facebook)
Мы хотим запросить и найти все сообщения для
user_id = 10
комментариев и отсортировать их поtimestamp
(дате).SQL ЗАПРОС
Составной PK позволяет Mysql фильтровать и сортировать результаты с помощью индекса; Mysql не нужно использовать временный файл или файловую сортировку для получения результатов. Без составного ключа это было бы невозможно и привело бы к очень неэффективному запросу.
Таким образом, составные ключи очень эффективны и подходят больше, чем простая проблема: «Я хочу искать,
column_a, column_b
поэтому я буду использовать составные ключи. Для моей текущей схемы базы данных у меня столько же составных ключей, сколько и одиночных ключей. Не упускайте из виду использование составного ключа!источник
Составные индексы полезны для
Составной индекс не может обрабатывать два диапазона. Я обсуждаю это далее в своей индексной кулинарной книге .
Найти ближайший - Если вопрос действительно в оптимизации
тогда ни один индекс не сможет обрабатывать оба измерения.
Вместо этого нужно «мыслить нестандартно». Если одно измерение реализуется посредством разделения, а другое - путем тщательного выбора
PRIMARY KEY
, можно значительно повысить эффективность для очень больших таблиц поиска по широте и долготе. В моем блоге latlng подробно рассказывается о том, как реализовать «поиск ближайшего» на земном шаре. Он включает код.Это
PARTITIONs
полосы диапазонов широты.PRIMARY KEY
Намеренно начинается с долготой , так что полезные строки, вероятно, будут в том же блоке. Хранимая процедура организует беспорядочный код для выполненияorder by... limit...
и увеличения «квадрата» вокруг цели, пока у вас не будет достаточно кофеен (или чего-то еще). Он также заботится о вычислениях по дуге большого круга и обработке линии дат и полюсов.Больше
Я написал еще один блог; он сравнивает 5 способов выполнения поиска по широте и долготе: http://mysql.rjweb.org/doc.php/latlng#presentation_choices (Ссылка, указанная выше, упоминается как один из 5.) Один из других способов - это, и указывает, что они оптимальны для конкретного случая :
То есть важно иметь оба столбца в двух индексах и не иметь индексов с одним столбцом для geolat и geolng.
источник
Нет никакого черного и белого, универсальный ответ.
Вы должны использовать составной индекс, если он будет полезен вашей рабочей нагрузке запроса.
Вам необходимо профилировать рабочую нагрузку вашего запроса, чтобы определить это.
Составной индекс вступает в игру, когда запросы могут быть полностью удовлетворены из этого индекса.
ОБНОВЛЕНИЕ (в ответ на редактирование опубликованного вопроса): если вы выбираете * из таблицы, можно использовать составной индекс, но нельзя. Для уверенности вам нужно будет запустить EXPLAIN PLAN .
источник
Для пространственного поиска вам понадобится R-Tree алгоритм , который позволяет очень быстро искать географические области. Именно то, что вам нужно для этой работы.
Некоторые базы данных имеют встроенные пространственные индексы. Быстрый поиск в Google показывает, что они есть в MySQL 5 (что, глядя на ваш SQL, я предполагаю, что вы используете MySQL).
источник
Составной индекс может быть полезен, когда вы хотите оптимизировать
group by
предложение (см. Эту статью http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html ). Пожалуйста, обратите внимание:источник
GROUP BY
не упоминалось.GROUP BY
не упоминалось в ОП.Я с @Mitch, полностью зависит от ваших запросов. К счастью, вы можете создавать и удалять индексы в любое время, и вы можете добавить ключевое слово EXPLAIN к своим запросам, чтобы увидеть, использует ли анализатор запросов индексы.
Если вы будете искать точную пару широта / долгота, этот индекс, вероятно, будет иметь смысл. Но вы, вероятно, будете искать дома на определенном расстоянии от определенного места, поэтому ваши запросы будут выглядеть примерно так (см. Источник ):
и, скорее всего, индекс вообще не поможет. Для геопространственных запросов вам понадобится что-то вроде этого .
Обновление: с этим запросом:
Анализатор запросов может использовать только индекс геолокации, или индекс только геолокацию, или, возможно, оба индекса. Я не думаю, что он будет использовать составной индекс. Но легко попробовать каждую из этих перестановок на реальном наборе данных, а затем (а) посмотреть, что вам говорит EXPLAIN, и (б) измерить время, которое действительно занимает запрос.
источник