PG的并行查询生产案例
作者:互联网
1.背景:
开发想通过web前端调用sql获取数据展现在内部平台上,发现查询较慢。
2.SQL分析:
PG环境
pg_tables=# select version();
version
----------------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 12.11 (Ubuntu 12.11-0ubuntu0.20.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
(1 row)
我拿来SQL直接贴下
EXPLAIN
SELECT
platform_name,
tid,
company_name_bill,
company_name_order,
shop_code_bill,
platform_code_bill,
shop_code_order,
platform_code_order,
brand_cn,
prosy_type,
category,
shop_name_bill,
shop_name_order,
status,
created,
pay_time,
consign_time,
sku_new,
product_id,
title,
sku_qy,
sales_price,
total_payment,
cost_to,
COST,
cost_sum,
sales_sum,
gross_profit,
gross_margin,
pay_no,
tracking_no,
logistics_company,
receiver_name,
receiver_address,
receiver_mobile,
buyer_nick,
is_refundamount,
expend_amount,
created_ex,
is_amount,
income_amount,
currency,
exchange_rate,
overseas_income,
overseas_expend,
is_overseas,
overseas_income_hkd,
overseas_expend_hkd,
created_in,
trading_channels,
currency_cny_rate,
post_fee,
up_time,
ts
FROM
cn_dw_tables.dw_order_info_detail_report_n
WHERE
company_name_bill = 'XXXXXX有限公司'
AND created_in BETWEEN '2022-03-26'
AND '2022-03-26'
AND platform_code_bill = 'xxxxxx'
AND shop_name_bill = 'XXXXXXX'
AND sku_new = 'xxxxxxxxx'
AND ts BETWEEN '2022-03'
AND '2022-03'
ORDER BY
created_in,pay_time DESC
LIMIT 100 发现基于ts字段进行了list分区。
去掉explain,查询花费了近3.891秒。
3.因为表的ts字段基于list分区,因为这台PG主要用于BI数据分析和审计或测试等作用,和使用人沟通暂时不能通过加索引方式解决,会影响其它报表dml使用。
经过explain分析,发现并行顺序扫描只有2个worker.
4.看下cpu核数(40核,说明下这台是台40核200G内存的dell物理机,在上面做了虚拟化,所以wokers planned也不能设置太高)
#cat /proc/cpuinfo |grep processor
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
processor : 8
processor : 9
processor : 10
processor : 11
processor : 12
processor : 13
processor : 14
processor : 15
processor : 16
processor : 17
processor : 18
processor : 19
processor : 20
processor : 21
processor : 22
processor : 23
processor : 24
processor : 25
processor : 26
processor : 27
processor : 28
processor : 29
processor : 30
processor : 31
processor : 32
processor : 33
processor : 34
processor : 35
processor : 36
processor : 37
processor : 38
processor : 39
#########查询配置中max_parallel_workers_per_gather大小
pg_tables=# show max_parallel_workers_per_gather;
max_parallel_workers_per_gather
---------------------------------
2
(1 row)
###增加worker数量为8
pg_tables=# alter system set max_parallel_workers_per_gather=8;
ALTER SYSTEM
pg_tables=# select * from pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)
pg_tables=# show max_parallel_workers_per_gather;
max_parallel_workers_per_gather
---------------------------------
8
(1 row)
再查发现只要1.81秒,over,大功告成!
4.原因分析:
Parallel Seq Scan”节点生成用于部分聚合的行。“Partial Aggregate”节点使用 SUM() 减少这些行。最后,每个worker进程的SUM计数器由“Gather”节点收集。 最终结果由“Finalize Aggregate”节点计算。
结合where条件,从数据页中逐个读取行不是因为并行读取;与普通的单线程选择相比,更复杂的查询速度提高了若干倍。
5.worker设置多大为好:
这个问题可以参考percona https://www.percona.com/blog/2019/02/21/parallel-queries-in-postgresql/
首先,max_parallel_workers_per_gather
参数是worker数量的最小限制。其次,查询执行程序从max_parallel_workers
大小限制的池中获取worker。最后,最顶层的限制是max_worker_processes
,它用来限制后台进程的总数。 工作分配失败会导致单进程执行。 查询计划可以根据表或索引大小减少worker数。min_parallel_table_scan_size
和min_parallel_index_scan_size
控制这一行为。
set min_parallel_table_scan_size='8MB'
8MB table => 1 worker
24MB table => 2 workers
72MB table => 3 workers
x => log(x / min_parallel_table_scan_size) / log(3) + 1 worker
每次表比minparallel(index | table)scansize
大3倍时,postgres会添加一个worker。worker数量不是以cost为基础的!循环依赖使得复杂的实现变得困难。相反,查询规划使用简单的规则。
实际上,这些规则在生产中并不总是可以接受,您可以使用ALTER TABLE ... SET(parallel_workers = N)
覆盖特定表的worker数量。
标签:name,并行,workers,gather,worker,查询,PG,max,parallel 来源: https://www.cnblogs.com/chinaops/p/16401094.html