У меня есть база данных MySQL InnoDB, доступ к которой осуществляется с сервера Django. У меня есть эта таблица:Почему мой запрос неоптимальный?
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| areasymbol | varchar(255) | NO | | NULL | |
| spatialver | int(11) | YES | | NULL | |
| lkey | int(11) | YES | | NULL | |
| musym | varchar(255) | NO | | NULL | |
| mukey | int(11) | YES | | NULL | |
| featsym | varchar(255) | NO | | NULL | |
| featkey | int(11) | YES | | NULL | |
| north | double | YES | MUL | NULL | |
| south | double | YES | MUL | NULL | |
| east | double | YES | MUL | NULL | |
| west | double | YES | MUL | NULL | |
| soil_type_id | int(11) | YES | MUL | NULL | |
+--------------+--------------+------+-----+---------+----------------+
В таблице в настоящее время содержит ~ 7-8 миллионов строк, и я ожидаю, что это будет по крайней мере в 3 раза, что многие, когда я закончу. Это статическая таблица. Мы импортируем, чтобы добавлять к нему вещи каждый раз в то время, но ничто не может быть изменено или удалено.
+-----------------+------------+----------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+----------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| soil_soilregion | 0 | PRIMARY | 1 | id | A | 7657769 | NULL | NULL | | BTREE | | |
| soil_soilregion | 1 | soil_soilregion_e733fdfc | 1 | soil_type_id | A | 15 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | north_soilregion | 1 | north | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | south_soilregion | 1 | south | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | east_soilregion | 1 | east | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | west_soilregion | 1 | west | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | north_south_east_west_soilregion | 1 | north | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | north_south_east_west_soilregion | 2 | south | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | north_south_east_west_soilregion | 3 | east | A | 7657769 | NULL | NULL | YES | BTREE | | |
| soil_soilregion | 1 | north_south_east_west_soilregion | 4 | west | A | 7657769 | NULL | NULL | YES | BTREE | | |
+-----------------+------------+----------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
У меня есть квадратный ящик на север/юг/восток/запад координаты, и я ищу для любой из этих областей, которые могут перекрываться, что окно
При запуске этого запроса к базе данных:
select *
from soil_soilregion
where east > -86.8379775155 AND north > 40.3782334957 AND
south < 40.3817576747 AND west < -86.8240119179;
это займет ~ 10 секунд, что неприемлемо. Когда я использую это объяснить то, что он говорит мне:
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | soil_soilregion | ALL | north_soilregion,south_soilregion,east_soilregion,west_soilregion,north_south_east_west_soilregion | NULL | NULL | NULL | 7657769 | Using where |
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
Когда я запускаю этот запрос в базе данных:
select *
from soil_soilregion
where east > -86.8379775155 AND east < -85.8379775155 AND
north > 40.3782334957 AND north < 41.3782334957 AND
south < 40.3817576747 AND south > 39.3817576747 AND
west < -86.8240119179 AND west > -87.8040119189;
Это занимает больше похоже на 6-7 секунд. Это лучше, но все еще субоптимально. Этот код по-прежнему будет работать, так как ни один объект не превышает 1 высокий или широкий (поэтому я дал ему максимальное расстояние в каждом направлении 1).
У меня есть несколько вопросов:
- Почему первый запрос не используя индексы? (Я предполагаю, что это связано с тем, что в диапазоне слишком много потенциальных элементов)
- Почему он никогда не использует мой составной индекс? Разве это не было бы оптимальным?
- Есть ли что-нибудь, что я могу сделать, чтобы улучшить этот запрос или мои индексы?
Примечание: Использование индекса силы имеет только отрицательные последствия.
Спасибо!
Edit 1: В соответствии с предложениями, я изменил запрос в том же порядке, как составной индекс, и это то, что я получил:
explain select * from soil_soilregion where north > 40.3782334957 AND south < 40.3817576747 AND east > -86.8379775155 AND west < -86.8240119179;
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | soil_soilregion | ALL | north_soilregion,south_soilregion,east_soilregion,west_soilregion,north_south_east_west_soilregion | NULL | NULL | NULL | 7657769 | Using where |
+----+-------------+-----------------+------+----------------------------------------------------------------------------------------------------+------+---------+------+---------+-------------+
вы пытаетесь изменить порядок утверждений в том месте? север Юг Восток Запад? – JamieD77
@ JamieD77 - Оптимизатор ничего не изменит, если вы измените порядок предложения WHERE. –
Пожалуйста, предоставьте 'SHOW CREATE TABLE'; он более описателен, чем 'DESCRIBE'. –