postgresql - PG 12 上的查询时间比 10 多 10 倍
问题描述
所以我在 Aurora r5.2xl 上有一个数据库,我在 i3.2xl(大量 IOPS)上创建了一个重复的数据库。出于某种原因,这一查询在新服务器上比在 Aurora 上花费的时间长 10 倍,即使所有变量都设置完全相同。
笔记:
- 我已经确定 100 倍的 IOP 不是问题,不是
- 所有设置和变量都相同
- 如果我在新服务器上提高限制,CPU 会以 100% 的速度燃烧,而在极光上它根本不会增加,因为查询运行得如此之快
- 所有索引都是相同的,我什至尝试过重新索引
- 数据是相同的(一个数据库有一些额外的行,但仅此而已)
- 尝试在两个表上进行真空分析
- 我为数据库做了一个 pg_dump 和 pg_restore
- 除了这个之外,几乎所有其他查询在新服务器上运行得更快
- 是的,这里使用了无顺序的限制,但这只是因为如果我不将其限制为 10,它将需要 1 小时以上才能完成,然后我才能发布极光 12 秒才能完成,而 psql 12 需要 1 小时以上。这更有效,不是问题的一部分
这是查询
explain analyze SELECT a.id,
count(b.id) as hotel_count,
array_agg(b.id) as hotel_ids
FROM autocomplete a,
hotel b
WHERE a.type = 'city'
AND st_covers(a.poly, b.coords)
AND st_distance(a.coords, b.coords) < 40000
AND b.last_seen IS NOT NULL
AND b.enabled = true
GROUP BY a.id
limit 10;
以下是极光结果
Limit (cost=0.83..1100.64 rows=10 width=56) (actual time=0.522..2.534 rows=10 loops=1)
-> GroupAggregate (cost=0.83..3696781.84 rows=33613 width=56) (actual time=0.521..2.531 rows=10 loops=1)
Group Key: a.id
-> Nested Loop (cost=0.83..3668393.17 rows=3729135 width=32) (actual time=0.357..2.506 rows=69 loops=1)
" -> Index Scan using ""PK_5523204bb8469c2025bcb0b55bc"" on autocomplete a (cost=0.42..188879.01 rows=33613 width=176) (actual time=0.025..0.280 rows=14 loops=1)"
" Filter: (type = 'city'::autocomplete_type_enum)"
Rows Removed by Filter: 133
-> Index Scan using hotel_coords_idx on hotel b (cost=0.41..103.49 rows=3 width=48) (actual time=0.109..0.158 rows=5 loops=14)
Index Cond: (a.poly && coords)
" Filter: ((last_seen IS NOT NULL) AND enabled AND _st_covers(a.poly, coords) AND (_st_distance(a.coords, coords, '0'::double precision, true) < '40000'::double precision))"
Rows Removed by Filter: 7
Planning time: 26.210 ms
Execution time: 2.590 ms
这是新的服务器结果(没有 iowait,但如果我将限制设置得更高,CPU 会一直以 100% 的速度燃烧)
Limit (cost=5215.44..28517.08 rows=10 width=56) (actual time=124.928..484.664 rows=10 loops=1)
-> GroupAggregate (cost=5215.44..80034722.29 rows=34345 width=56) (actual time=124.926..484.643 rows=10 loops=1)
Group Key: a.id
-> Gather Merge (cost=5215.44..80000159.03 rows=4551193 width=32) (actual time=89.883..559.222 rows=69 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Nested Loop (cost=4215.41..79473838.41 rows=1896330 width=32) (actual time=38.777..468.633 rows=162 loops=3)
" -> Parallel Index Scan using ""PK_5523204bb8469c2025bcb0b55bc"" on autocomplete a (cost=0.42..92511.37 rows=14310 width=176) (actual time=0.017..0.159 rows=12 loops=3)"
" Filter: (type = 'city'::autocomplete_type_enum)"
Rows Removed by Filter: 84
-> Bitmap Heap Scan on hotel b (cost=4214.99..5547.18 rows=8 width=48) (actual time=37.861..37.959 rows=13 loops=37)
Recheck Cond: (last_seen IS NOT NULL)
Rows Removed by Index Recheck: 11
" Filter: (enabled AND st_covers(a.poly, coords) AND (st_distance(a.coords, coords, true) < '40000'::double precision))"
Rows Removed by Filter: 1
Heap Blocks: exact=107
-> BitmapAnd (cost=4214.99..4214.99 rows=26 width=0) (actual time=37.759..37.759 rows=0 loops=37)
-> Bitmap Index Scan on hotel_coords_idx (cost=0.00..2.60 rows=117 width=0) (actual time=0.910..0.910 rows=59 loops=37)
Index Cond: (coords && a.poly)
-> Bitmap Index Scan on hotel_last_seen_idx (cost=0.00..4149.68 rows=258652 width=0) (actual time=36.268..36.268 rows=262908 loops=37)
Planning Time: 1.815 ms
Execution Time: 559.530 ms
知道为什么会这样吗?我不知所措。新服务器实际上在一系列查询上击败了 aurora,包括诸如“explain analyze select name from hotel where last_seen is not null and enabled = true group by name limit 1000;”之类的查询。但由于某种原因,上面的查询运行速度要慢得多
解决方案
好的,所以我发现无论我尝试什么,PG12 对该查询的优化都非常糟糕。当我这样重写它时,它的工作速度也一样快。
WITH x AS
(
SELECT id, poly, coords
FROM autocomplete
WHERE type = 'city'
)
SELECT x.id,
sum(CASE WHEN last_seen IS NOT NULL THEN 1 ELSE 0 END) AS hotel_count,
array_agg(CASE WHEN last_seen IS NOT NULL THEN b.id ELSE NULL END) AS hotel_ids
FROM x, hotel b
WHERE st_covers(x.poly, b.coords)
AND st_distance(x.coords, b.coords) < 40000
AND b.enabled = true
GROUP BY x.id;
PS12 还在每个循环中对 last_seen 进行全索引扫描,导致它永远消失,因此从 where 删除 last_seen 并出于某种原因将其添加到计数条件中会便宜很多
推荐阅读
- r - 如何在 R 中为每个不同的观察添加一组行
- python - 获取数据框内的特定值和位置
- flutter - Flutter 中显示变量的即时更新(更改变量值后)
- powerbi - 在 power bi 中将 SUMPRODUCT 公式创建为 dax 格式
- python - 如何将不同的数据集与日期时间索引合并?
- android - 改善 recycleView 项目之间的间距
- c# - 是否可以设置模型在 web api 2 中的绑定方式?
- laravel - Laravel - 在条件内循环时元素显示两次
- azure-ad-b2c - B2C Validation of REST API
- vue.js - Vue.js Axios 发布请求从 Laravel (API) 获取超时