【问题标题】:PostgreSQL how to create a scalable location-based queryPostgreSQL 如何创建可扩展的基于位置的查询
【发布时间】:2013-11-13 01:37:20
【问题描述】:

我需要建议,因为我不够好。

我在 PostgreSQL 中有一个在 AWS(亚马逊网络服务)上运行的数据库。 我有一个表“user_location”,其中存储了每个用户的位置,现在有超过 300 万行。

我有一个脚本经常运行以下查询,以查看附近是否有两个用户:

SELECT
    UL.id                          AS id, 
    UL.user_id                     AS user_id, 
    ST_X(UL.location::geometry)    AS lat, 
    ST_Y(UL.location::geometry)    AS lng, 
    UL.datetime                    AS datetime
FROM 
    public.user_location AS UL
WHERE 
    UL.user_id <> 1234567890 AND 
    '1890-10-31 03:00:00 +00:00' - UL.datetime <= interval '1' minute AND
    '1890-10-31 03:00:00 +00:00' >= UL.datetime AND
    ST_DWithin(UL.location, ST_GeogFromText('POINT(54 -1)'), 5000)
ORDER BY
    UL.datetime DESC;

问题似乎是半径,查询的执行时间随着半径的增加呈指数增长,因为它需要检查更多的行。

我需要一个可扩展的解决方案,通过增加给定位置周围的半径,执行时间几乎相同。我需要在日期时间之前和查询中的半径之后使用“水平切割”数据,我该怎么办?

我还有 EXPLAIN ANALYZE 的输出:

"Sort  (cost=389.72..389.73 rows=3 width=52) (actual time=136848.985..136848.985 rows=0 loops=1)"
"  Sort Key: datetime"
"  Sort Method: quicksort  Memory: 25kB"
"  ->  Bitmap Heap Scan on user_location ul  (cost=11.00..389.70 rows=3 width=52) (actual time=136848.976..136848.976 rows=0 loops=1)"
"        Recheck Cond: (location && '0101000020E6100000C182458F29494B4095E0C3DB39E3F3BF'::geography)"
"        Filter: ((user_id <> 1234567890) AND ('1890-10-31 03:00:00 +00:00'::timestamp with time zone >= datetime) AND (('1890-10-31 03:00:00 +00:00'::timestamp with time zone - datetime) <= '00:01:00'::interval minute) AND ('0101000020E6100000C182458F29494B4095E0C3DB39E3F3BF'::geography && _st_expand(location, 5000::double precision)) AND _st_dwithin(location, '0101000020E6100000C182458F29494B4095E0C3DB39E3F3BF'::geography, 5000::double precision, true))"
"        ->  Bitmap Index Scan on users_locations_gix  (cost=0.00..11.00 rows=91 width=0) (actual time=4463.249..4463.249 rows=165622 loops=1)"
"              Index Cond: (location && '0101000020E6100000C182458F29494B4095E0C3DB39E3F3BF'::geography)"
"Total runtime: 136849.591 ms"

提前致谢! 干杯

【问题讨论】:

    标签: sql postgresql scalability postgis


    【解决方案1】:

    对于 300 万行,您将希望减少查询实际需要评估的数量。要做到这一点,最好我们知道您的数据是什么样的,但是有一些相当简单的事情需要查看。

    您在指定的一分钟内预计有多少条目?我猜应该很低。如果是这样,您可以在UL.datetime 上放置一个索引(默认btree 很好)(不要忘记在VACUUM and ANALYZE 之后)。然后更改您的查询,以便它能够很好地利用它。

     UL.datetime BETWEEN '1890-10-31 03:00:00 +00:00'
                     AND '1890-10-31 03:00:00 +00:00' + interval '1' minute AND
    

    如果这些日期之间的行数过多,我们将需要找到一种方法来限制需要通过位置评估的内容。

    【讨论】:

    • 谢谢@cmd!我认为使用between ... and ... 查询变得可搜索。我正在创建一个索引(datetime DESC),但这需要时间。我不知道它取决于用户数量的多少条目,所以它应该或多或少1000个条目。
    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    相关资源
    最近更新 更多