我一直在努力解决1000多个标记的标记聚类问题(应该放在Google地图上)。我不是非常热衷于使用所有标记渲染大型JSON结构,我也不喜欢使用PostGIS进行一些复杂的服务器“geo”计算。
我想出的解决方案是将世界地图划分为某种分层空间树,比方说quad tree,其中我的数据库中的每个点都将在该树中分配“坐标”。这些坐标是具有on position_x index_of_tile in tier_x
的字符串,例如'031232320012'。字符串的长度取决于将为前端映射启用的缩放级别数。基本上,如果用户移动或缩放地图,我将使用当前缩放级别启动Ajax GET请求并将端口坐标视为参数。然后在后端我打算构建一个应该指向“给定缩放级别的视口”的字符串,例如'02113'我希望在树坐标列中找到所有带有此前缀('02113')的点。
编辑:我还需要快速GROUP BY,例如SELECT count(*) from points GROUP BY left(coordinates, 5);
我的问题是如何尽快执行这些操作?我的数据库是PostgreSQL。
答案 0 :(得分:2)
然后在后端我打算构建一个应该指向“给定缩放级别的视口”的字符串,例如'02113'我希望在树坐标列中找到所有带有此前缀('02113')的点。
只要您在索引列中查看字符串中最左边的五个(或六个或七个)字符,普通索引就可以在任何现代dbms上运行良好。
SELECT ...
...
WHERE column_name LIKE '02113%';
在PostgreSQL中,您还可以构建index on an expression。所以你可以在前五个字符上创建一个索引。
CREATE INDEX your_index_name ON your_table (left(column_name, 5));
我希望PostgreSQL的查询优化器能够选择正确的索引,如果有三个或四个这样的话。 (一个用于5个字符,一个用于6个字符等)
我构建了一个表,并用一百万行随机数据填充它。
在以下查询中,PostgreSQL的查询优化器确实选择了正确的索引。
explain analyze
select s
from coords
where left(s, 5) ='12345';
它在0.1毫秒内返回。
我还使用GROUP BY进行了测试。同样,PostgreSQL的查询优化器选择了正确的索引。
"GroupAggregate (cost=0.00..62783.15 rows=899423 width=8) (actual time=91.300..3096.788 rows=90 loops=1)"
" -> Index Scan using coords_left_idx1 on coords (cost=0.00..46540.36 rows=1000000 width=8) (actual time=0.051..2915.265 rows=1000000 loops=1)"
"Total runtime: 3096.914 ms"
GROUP BY子句中的left(name, 2)
之类的表达式将要求PostgreSQL触及索引中的每一行,如果不是表中的每一行。这就是为什么我的查询花了3096ms;它必须触及索引中的一百万行。但是你可以从EXPLAIN计划中看到它使用了索引。
通常,我希望地理应用程序对PostGIS表使用边界框来减少您访问的行数。如果你的四叉树实现不能做得更好,我会坚持使用PostGIS足够长的时间来成为它的专家。 (在你花了一些时间之前,你不会确定它无法完成这项工作。)