【发布时间】:2015-08-06 18:21:03
【问题描述】:
我有一个从 Django 服务器访问的 MySQL InnoDB 数据库。我有这张桌子:
+--------------+--------------+------+-----+---------+----------------+
| 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)。
我有几个问题:
- 为什么第一个查询不使用索引? (我认为这是因为该范围内的潜在项目太多)
- 为什么它从不使用我的复合索引?那不是最理想的吗?
- 我能做些什么来改进这个查询或我的索引吗?
注意:使用力指数只会产生负面影响。
谢谢!
编辑 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 - 如果您重新排序
WHERE子句,优化器不会做任何不同的事情。 -
请提供
SHOW CREATE TABLE;它比DESCRIBE更具描述性。