我有一个大型数据集(大约190万行)我正在选择的3D点。我最常使用的陈述类似于:
SELECT * FROM points
WHERE x > 100 AND x < 200
AND y > 100 AND y < 200
AND z > 100 AND z < 200
AND otherParameter > 10
我有x,y和z以及otherParameter的标记。我也试过为x,y,z添加一个多部分索引,但这没有帮助。
有关如何更快地进行此SELECT
查询的任何建议吗?
答案 0 :(得分:6)
B-Tree
索引对这样的查询没有多大帮助。
作为R-Tree
索引需要什么,以及对它的最小边界平行六面体查询。
不幸的是,MySQL
不支持R-Tree
个3d
点以上的2d
个索引,仅X
。但是,您可以在Y
和B-Tree
上创建一个索引,这对X
和Y
上的任何ALTER TABLE points ADD xy POINT;
UPDATE points
SET xy = Point(x, y);
ALTER TABLE points MODIFY xy POINT NOT NULL;
CREATE SPATIAL INDEX sx_points_xy ON points (xy);
SELECT *
FROM points
WHERE MBRContains(LineString(Point(100, 100), Point(200, 200), xy)
AND z BETWEEN 100 and 200
AND otherParameter > 10;
索引更具选择性单独:
MyISAM
仅当您的表格为{{1}}时才可以这样做。
答案 1 :(得分:-1)
我没有测试mySQL,但我很好奇它的INTERSECT有多高效:
select points.*
from points
join
(
select id from points where x > 100 AND x < 200
intersect
select id from points where y > 100 AND y < 200
intersect
select id from points where z > 100 AND z < 200
) as keyset
on points.id = keyset.id
不一定推荐这个 - 但是要尝试一下,特别是如果你在x,y和z上有单独的索引。
编辑:由于mySQl不支持INTERSECT,因此可以使用内联视图的JOINS重写上述查询。每个视图都包含一个键集,每个视图都具有您在x,y和z上放置的单独索引的优势。性能取决于返回的键的numnber和交叉/连接算法。
我首先测试了交叉方法(在SQLite中),看看是否有办法提高空间查询的性能,而不是使用它们的R-Tree模块。 INTERSECT实际上比在其中一个空间值上使用单个非复合索引慢,然后扫描基表的子集以获得其他空间值。但结果可能会有所不同,具体取决于数据库的大小。在表达到庞大的大小并且磁盘i / o作为性能因素变得更加重要之后,交叉离散键集可能更有效,每个离散键集都已经从索引实例化,而不是扫描基表的次要表。到索引的初始获取。