在MySQL中使用空间索引时性能不佳

时间:2011-01-21 11:15:25

标签: mysql database performance gis spatial

我正在尝试推动一个非地理空间但非常适合的数据集的小实验,并且发现结果有点令人不安。数据集是基因组数据,例如人类基因组,我们有一个DNA区域,其中像基因这样的元素占据特定的起点和终点坐标(我们的X轴)。我们有多个DNA区域(染色体)占据Y轴。目标是沿着单个Y坐标返回与两个X坐标相交的所有项目,例如, 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行),似乎效果很好。当这个增加超过300万行标记时,MySQL拒绝使用空间索引,并且当它被迫使用它时速度较慢(使用全表扫描时为40秒对5秒)。当添加更多数据时,索引开始被使用,但性能损失仍然存在。强制索引关闭将查询降低到8秒。我正在使用的查询如下:

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

进入此区域的数据沿着Y维度非常密集(想象一下,就像你在很长的路上记录了每个建筑物,电话亭,邮箱和鸽子的位置)。我已经测试了R-Indexes如何在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`)

仍然没有突出显示此查询的性能如此差的原因

在阅读@ rickonrails @Fraser发布的文章后,问题似乎与索引不在内存中有关。如果我将类似的技术应用于文章中提到的那些(确实使密钥缓冲区非常大),然后我强制查询使用索引查询时间plumet。我们仍然看到查询一个地区和一个地区之间的滞后。然后搜索该区域的一个子集,但它都指向使索引的负载正确。

这个故事的寓意是什么? MySQL中的R-Indexes在内存中具有相当差的性能,然后它们具有出色的性能。对于我想要做的事情来说,这并不是一个很好的解决方案,但它仍然为MySQL提供了一个有趣的角度。

感谢所有人的帮助。

4 个答案:

答案 0 :(得分:1)

从EXPLAIN计划中我们看到虽然空间可能用于查询(' possible_keys'列),但它未被使用(' key'列中为NULL)。 我不确定为什么它不是自动选择的,但您可以通过使用强制索引'在查询中指定它来明确指示MySql使用索引。子句:

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);

答案 1 :(得分:0)

  

目标是带回所有   与两个X相交的项目   沿着一个Y坐标   坐标

您是否考虑过使用多个字段的索引?像:

CREATE INDEX spacial_search ON spatial_feature(y, x)

如果您使用的是一组有限的y值,则可以使用此方法。

答案 2 :(得分:0)

我拥有遗传学学位,而且我是一名程序员,你不需要使用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);

顺便说一句,染色体是非常长的字符串(就像数据一样)你可以(加速它们像blob一样转储它们(即编码基因和垃圾DNA)

答案 3 :(得分:0)

您确定要使用关系数据库吗?如果我是你,我会把你的数据集推送到Solr或Elastic Search(可能将主数据集存储在别处)。这些引擎是为索引而构建的,您会注意到响应时间的差异。