explain analyze和直接执行SQL时间相差10倍?

explain analyze和直接执行SQL时间相差10倍?

脑子转了半天不知从何入手,同事们说vacuum analyze 、重启一下看看、断开重连看看、换个工具看看。

我首先对表进行vacuum analyze,发现这个情况竟然还存在。

其次我使用psql 通过远程链接的方式进去,执行时间并不长。也只是19秒,这里explain (analyze,buffers) 也是19秒是正常的。通过show all检查了psql 和dbeaver的参数情况,也没有什么区别。

这里就奇怪了。问了一下同事,说是有可能两次SQL走的执行计划不同。

此时我就纳闷dbeaver和psql会影响执行计划?explain analyze 和直接跑SQL还能走不同的执行计划?

先上auto_explain看看

sql 复制代码
LOAD 'auto_explain';   
## 变更postgresql.conf的以下参数配置。
session_preload_libraries = 'auto_explain'; 
auto_explain.log_analyze = on;
auto_explain.log_buffers = on;
auto_explain.log_min_duration = 15000;

操作完以上配置,再把SQL执行一遍,毫无意外explain (analyze,buffers) 和直接跑SQL 依然有较大差距(在dbeaver客户端依然是稳定复现),且仔细一看其真实的扫描行数两者也有区别。

执行计划使用的Nested Loop,以上驱动表的统计信息有所区别。

德哥:"并行的我印象中是展示的某个worker的统计信息不知道现在代码改了没"

对比执行计划:
·auto_explain获取到直接跑SQL的执行计划其Workers Loaunched 0。
·而使用explain anlyze 的执行计划其Workers Loaunched 8。是用到了8个并行工作组。

当Workers Loaunched 0 且Workers Planned 8,其parallel 都是由单一的work节点进行scan。这两种情况下其leader统计出来的统计信息也有区别。

初步咋一看 ,在Workers Loaunched 0 的情况下其驱动表的(sum(rows*loop))真实扫描行数的总和正好等于append节点的真实扫描行数

在Workers Loaunched 8 的情况下其驱动表的统计信息就有所不同,其真实扫描行数

448540*9=4036860 正好比真实扫描行数多1。这里parallel是8+1(leader节点),

由于真实行数为4036859/9(8 works + leader)≈ 448539.8888

所以该append节点的真实扫描行数并非是精确的。可能由于边界重叠或任务重复领取或者非平均分配导致。

具体该段的算法,待后续看完这相关的源码的上下文,在下一篇文章中再做解释。

为什么explain analyze可以启动并行工作组,直接执行SQL就无法启动并行工作组?

执行的时间差距较大,还是因为并行工作组的未能启用导致。那为什么直接跑并行工作组就起不来呢?

首先,并行的工作组是向parallel worker pool进行申请,plan->num_workers; 。如果work pool中无法满足所需数量,此时便不会为其分配并行工作组。由于当前环境无法进行debug,这个在本地环境复现了我再在后续文章中更新。

这里排除了参数的影响

复制代码
/**检查并行相关参数**/
  select current_setting('enable_parallel_append') as enable_parallel_append
  ,current_setting('enable_parallel_hash') as enable_parallel_hash
  --,current_setting('force_parallel_mode') as force_parallel_mode   --16以后取消该参数
  ,current_setting('parallel_leader_participation') as parallel_leader_participation
  ,current_setting('max_parallel_workers') as max_parallel_workers
  ,current_setting('max_parallel_workers_per_gather') as max_parallel_workers_per_gather
  ,current_setting('max_worker_processes') as max_worker_processes;

max_parallel_workers

👉 实例级别最多能开多少个并行 worker。

max_worker_processes

👉 后台总 worker 数量上限,低于 max_parallel_workers 时会限制并行。

max_parallel_workers_per_gather

👉 单个 Gather/Gather Merge 节点最多能用多少个 worker。

相关推荐
向宇it3 小时前
【Mysql知识】Mysql索引相关知识详解
数据库·mysql
文人sec4 小时前
性能测试-jmeter13-性能资源指标监控
数据库·测试工具·jmeter·性能优化·模块测试
摩羯座-185690305946 小时前
VVIC 平台商品详情接口高效调用方案:从签名验证到数据解析全流程
java·前端·数据库·爬虫·python
论迹6 小时前
【Redis】-- 分布式锁
数据库·redis·分布式
沉迷技术逻辑6 小时前
Redis-实现分布式锁
数据库·redis·缓存
小志开发7 小时前
SQL从入门到起飞:完整数据库操作练习
数据库·sql·学习·oracle·sqlserver·navicat
或与且与或非7 小时前
rust使用sqlx示例
开发语言·数据库·rust
王不忘.7 小时前
MySQL 数据库核心知识点详解
数据库·mysql
时序数据说7 小时前
时序数据库 IoTDB:支撑万亿级物联网设备的基石
大数据·数据库·物联网·时序数据库·iotdb