WEBKT

PostgreSQL 并行查询加速窗口函数与聚合函数实战:性能起飞的秘密

48 0 0 0

1. 啥是并行查询?

2. 窗口函数与并行查询

2.1. 开启并行窗口函数

2.2. 实战演示:并行窗口函数

3. 聚合函数与并行查询

3.1. 开启并行聚合

3.2. 实战演示:并行聚合

4. 并行查询的注意事项

5. 总结

“喂,哥们,你还在为 PostgreSQL 慢查询头疼吗?”

“可不是嘛!特别是涉及到窗口函数和聚合函数,那速度,简直让人抓狂!”

“嘿嘿,试试并行查询吧!PostgreSQL 的并行查询,可是个‘大杀器’,用好了,能让你的查询性能原地起飞!”

“并行查询?听起来很高大上啊,具体怎么搞?”

别急,今天咱们就来好好聊聊 PostgreSQL 并行查询在窗口函数和聚合函数中的应用,手把手教你如何榨干 PostgreSQL 的性能潜力,让你的查询速度“嗖嗖嗖”地往上窜!

1. 啥是并行查询?

在解释并行查询之前,咱们先来想象一个场景:你一个人搬一堆砖头,累死累活,效率还低。但如果找几个帮手一起搬,那速度不就快多了?

PostgreSQL 的并行查询,就类似于这个“找帮手”的过程。它将一个大的查询任务,拆分成多个小的子任务,然后分配给多个 CPU 核心(或者说“工人”)同时执行,最后再把结果汇总起来。这样一来,原本需要串行执行的任务,变成了并行执行,查询速度自然就大幅提升了。

PostgreSQL 从 9.6 版本开始引入并行查询,并在后续版本中不断增强。目前,PostgreSQL 已经支持并行顺序扫描、并行 Join(包括 Nested Loop、Hash Join 和 Merge Join)、并行聚合、并行窗口函数等。

2. 窗口函数与并行查询

窗口函数,是 PostgreSQL 中非常强大的一类函数。它可以对查询结果集中的每一行,都计算出一个基于“窗口”的值。这个“窗口”,可以理解为与当前行相关的一组行。常见的窗口函数有 ROW_NUMBER()RANK()DENSE_RANK()NTILE()LAG()LEAD() 等。

在默认情况下,PostgreSQL 的窗口函数是串行执行的。也就是说,它会逐行处理数据,计算窗口函数的值。当数据量很大时,这种串行执行方式就会成为性能瓶颈。

而并行查询,则可以打破这个瓶颈。PostgreSQL 可以将窗口函数的计算任务,分配给多个“工人”并行执行。每个“工人”负责处理一部分数据,计算出各自的窗口函数值,最后再由“领导者进程”将结果汇总起来。

2.1. 开启并行窗口函数

要让 PostgreSQL 对窗口函数执行并行查询,需要满足以下几个条件:

  • PostgreSQL 版本 >= 9.6
  • 查询中不包含 ORDER BY 子句,或者 ORDER BY 子句中的列与 PARTITION BY 子句中的列相同。这是因为,如果 ORDER BY 子句与 PARTITION BY 子句不同,PostgreSQL 需要对数据进行全局排序,而这会破坏并行性。
  • 设置合适的并行度参数max_parallel_workers_per_gathermax_worker_processesmax_parallel_workers。这些参数控制了 PostgreSQL 可以使用的最大并行工作进程数。

2.2. 实战演示:并行窗口函数

假设我们有一张名为 sales 的表,记录了每个销售员在每个月的销售额。现在,我们要计算每个销售员每个月的销售额排名。

-- 创建 sales 表
CREATE TABLE sales (
salesman_id INT,
month INT,
sales_amount NUMERIC
);
-- 插入测试数据
INSERT INTO sales (salesman_id, month, sales_amount)
VALUES
(1, 1, 1000),
(1, 2, 1200),
(1, 3, 1500),
(2, 1, 800),
(2, 2, 900),
(2, 3, 1100),
(3, 1, 1200),
(3, 2, 1400),
(3, 3, 1600);
-- 串行执行窗口函数
EXPLAIN ANALYZE
SELECT
salesman_id,
month,
sales_amount,
RANK() OVER (PARTITION BY salesman_id ORDER BY sales_amount DESC) AS sales_rank
FROM
sales;
-- 开启并行查询
SET max_parallel_workers_per_gather = 2;
SET max_worker_processes =8;
SET max_parallel_workers = 8;
EXPLAIN ANALYZE
SELECT
salesman_id,
month,
sales_amount,
RANK() OVER (PARTITION BY salesman_id ORDER BY sales_amount DESC) AS sales_rank
FROM
sales;

通过对比两次 EXPLAIN ANALYZE 的输出,你会发现,开启并行查询后,查询计划中出现了 Gather 节点,并且 Workers Planned 的值大于 0。这表明 PostgreSQL 确实使用了并行查询来执行窗口函数。

观察Execution Time, 并行查询一般会更优. (数据量小时可能看不出差别, 当数据量足够大时, 优势就体现出来了).

3. 聚合函数与并行查询

聚合函数,也是 PostgreSQL 中常用的一类函数。它可以对一组数据进行汇总计算,得到一个单一的结果。常见的聚合函数有 COUNT()SUM()AVG()MIN()MAX() 等。

与窗口函数类似,PostgreSQL 的聚合函数在默认情况下也是串行执行的。但通过并行查询,我们可以将聚合计算任务分配给多个“工人”并行执行,从而提高查询速度。

3.1. 开启并行聚合

要让 PostgreSQL 对聚合函数执行并行查询,需要满足以下几个条件:

  • PostgreSQL 版本 >= 9.6
  • 查询中不包含 GROUP BY 子句,或者 GROUP BY 子句中的列是表的主键或唯一键。这是因为,如果 GROUP BY 子句中的列不是主键或唯一键,PostgreSQL 需要对数据进行分组,而这会破坏并行性。
  • 设置合适的并行度参数。 同窗口函数.

3.2. 实战演示:并行聚合

还是以 sales 表为例,现在我们要计算每个销售员的总销售额。

-- 串行执行聚合函数
EXPLAIN ANALYZE
SELECT
salesman_id,
SUM(sales_amount) AS total_sales
FROM
sales
GROUP BY
salesman_id;
-- 开启并行查询
SET max_parallel_workers_per_gather = 2;
EXPLAIN ANALYZE
SELECT
salesman_id,
SUM(sales_amount) AS total_sales
FROM
sales
GROUP BY
salesman_id;

同样,通过对比两次 EXPLAIN ANALYZE 的输出,你可以看到并行查询的效果。 请注意Gather节点和Workers Planned的值。

4. 并行查询的注意事项

并行查询虽好,但也不是万能的。在使用并行查询时,还需要注意以下几点:

  • 并非所有查询都能并行化。PostgreSQL 的并行查询,目前还存在一些限制。例如,包含某些特定操作符、函数或子查询的查询,可能无法并行化。
  • 并行度并非越高越好。过高的并行度,可能会导致资源竞争加剧,反而降低查询性能。一般来说,建议将并行度设置为 CPU 核心数的 2-4 倍。
  • 并行查询会增加系统开销。并行查询需要启动多个工作进程,这会增加系统的 CPU、内存和 I/O 开销。因此,对于一些简单的查询,或者数据量很小的查询,使用并行查询可能反而会更慢。
  • 注意死锁风险. 并行查询增加了死锁的可能性, 特别是当多个查询同时更新同一张表时. 要注意事务隔离级别和锁的使用.
  • 监控并行查询性能. 使用pg_stat_activity视图可以监控当前正在运行的查询是否使用了并行工作进程, 以及并行工作进程的状态.

5. 总结

PostgreSQL 的并行查询,是一个强大的性能优化工具。通过将查询任务拆分成多个子任务,并行执行,可以显著提高窗口函数和聚合函数的查询速度。但同时,我们也需要注意并行查询的限制和注意事项,合理使用并行查询,才能真正发挥它的威力。

“怎么样,哥们,现在对 PostgreSQL 的并行查询有点感觉了吧?”

“嗯嗯,感觉打开了新世界的大门!以后再也不怕慢查询了!”

“哈哈,那就赶紧去试试吧!记住,实践出真知,多动手,多尝试,你也能成为 PostgreSQL 高手!”

希望这篇文章能帮助你更好地理解和使用 PostgreSQL 的并行查询。如果你还有其他问题,欢迎留言讨论!

PostgreSQL砖家 PostgreSQL并行查询性能优化

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/7744