0

我一直在努力解决 1000 多个标记的标记聚类问题(应该放在谷歌地图上)。我不太热衷于使用所有标记渲染大型 JSON 结构,也不喜欢使用 PostGIS 进行一些复杂的服务器“地理”计算。

我想出的解决方案是将世界地图划分为某种分层空间树,比如说四叉树,其中我的数据库中的每个点都将在该树中分配有“坐标”。这些坐标是具有 的字符串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。

4

1 回答 1

2

然后在后端我计划构建一个应该指向“给定缩放级别的视口”的字符串,例如'02113',我想在树坐标列中找到所有具有此前缀('02113')的点.

只要您在索引列中查看字符串的最左侧五个(或六个或七个)字符,普通索引就应该在任何现代 dbms 上表现良好。

SELECT ...
...
WHERE column_name LIKE '02113%';

在 PostgreSQL 中,您还可以在表达式上构建索引。所以你可以在前五个字符上创建一个索引。

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 接触索引中的每一行,如果不是表中的每一行的话。这就是为什么我的查询需要 3096 毫秒;它必须触及索引中的一百万行。但是你可以从 EXPLAIN 计划中看到它使用了索引。

通常,我希望地理应用程序对 PostGIS 表使用边界框来减少您访问的行数。如果你的四叉树实现不能做得比这更好,我会坚持使用 PostGIS 足够长的时间来成为它的专家。(在你花一些时间之前,你不会确定它不能完成这项工作。)

于 2013-04-23T17:05:21.543 回答