Postgresql源码(106)Generic Plan与Custom Plan的区别(以分区表为例)

相关:
《Postgresql源码(105)分区表剪枝代码分析》
《Postgresql源码(106)Generic Plan与Custom Plan的区别(以分区表为例)》

实例

CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

CREATE TABLE measurement_y2006m01 PARTITION OF measurement FOR VALUES FROM ('2006-01-01') TO ('2006-02-01');
CREATE TABLE measurement_y2006m02 PARTITION OF measurement FOR VALUES FROM ('2006-02-01') TO ('2006-03-01');
CREATE TABLE measurement_y2006m03 PARTITION OF measurement FOR VALUES FROM ('2006-03-01') TO ('2006-04-01');
CREATE TABLE measurement_y2006m04 PARTITION OF measurement FOR VALUES FROM ('2006-04-01') TO ('2006-05-01');
CREATE TABLE measurement_y2006m05 PARTITION OF measurement FOR VALUES FROM ('2006-05-01') TO ('2006-06-01');

insert into measurement values (1, '2006-01-03', floor(random() * 100), floor(random() * 100));
insert into measurement values (2, '2006-02-04', floor(random() * 100), floor(random() * 100));
insert into measurement values (3, '2006-03-05', floor(random() * 100), floor(random() * 100));
insert into measurement values (4, '2006-03-06', floor(random() * 100), floor(random() * 100));
insert into measurement values (5, '2006-03-07', floor(random() * 100), floor(random() * 100));
insert into measurement values (6, '2006-03-08', floor(random() * 100), floor(random() * 100));
insert into measurement values (7, '2006-04-09', floor(random() * 100), floor(random() * 100));
insert into measurement values (8, '2006-04-10', floor(random() * 100), floor(random() * 100));
insert into measurement values (9, '2006-05-11', floor(random() * 100), floor(random() * 100));
insert into measurement values (10, '2006-05-12', floor(random() * 100), floor(random() * 100));
prepare p1 (date, date) as select * from measurement where logdate between $1 and $2;

explain analyze execute p1('2006-04-05', '2006-04-20');

首先看Custom Plan(强制choose_custom_plan返回true)

postgres=# explain analyze execute p1('2006-04-05', '2006-04-20');

                                                         QUERY PLAN                                                         
----------------------------------------------------------------------------------------------------------------------------
 Seq Scan on measurement_y2006m04 measurement  (cost=0.00..37.75 rows=9 width=16) (actual time=0.017..0.020 rows=6 loops=1)
   Filter: ((logdate >= '2006-04-05'::date) AND (logdate <= '2006-04-20'::date))
 Planning Time: 1620.157 ms
 Execution Time: 0.041 ms

再看Generic Plan(强制choose_custom_plan返回false)

postgres=# explain analyze execute p1('2006-04-05', '2006-04-20');
                                                             QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
 Append  (cost=0.00..188.97 rows=45 width=16) (actual time=0.027..0.034 rows=6 loops=1)
   Subplans Removed: 4
   ->  Seq Scan on measurement_y2006m04 measurement_1  (cost=0.00..37.75 rows=9 width=16) (actual time=0.024..0.028 rows=6 loops=1)
         Filter: ((logdate >= $1) AND (logdate <= $2))
 Planning Time: 28898.081 ms
 Execution Time: 0.102 ms
(6 rows)

问题一:看起来都剪枝了?

是的,从计划上来看,只能看到4月表,确实都剪枝了。

但仔细看还是有区别的,Generic Plan多了一行Subplans Removed: 4。这表示Generic计划实际是没剪枝的,是运行时做的prune。

证明:查看GetCachedPlan生成plan,可以看到下面的计划树把每个月分片都戴上了,明显未剪枝:
在这里插入图片描述
计划中是没剪枝的,但在计划中记录了裁剪的信息:make_partition_pruneinfo。

然后在执行器启动阶段:

#0  ExecInitAppend (node=0x17435a8, estate=0x173b3b0, eflags=16) at nodeAppend.c:111
#1  0x00000000007566d8 in ExecInitNode (node=0x17435a8, estate=0x173b3b0, eflags=16) at execProcnode.c:182
#2  0x000000000074c12c in InitPlan (queryDesc=0x1737b48, eflags=16) at execMain.c:938
#3  0x000000000074b112 in standard_ExecutorStart (queryDesc=0x1737b48, eflags=16) at execMain.c:265
#4  0x000000000074ae78 in ExecutorStart (queryDesc=0x1737b48, eflags=0) at execMain.c:144
#5  0x00000000006a69fc in ExplainOnePlan (plannedstmt=0x1743510, into=0x0, es=0x1744b70,  queryString=0x17287d0 "prepare p1 (date, date) as select * from measurement where logdate between $1 and $2;", params=0x1744e58, queryEnv=0x0, planduration=0x7ffc0dc5c470,  bufusage=0x0) at explain.c:579
#6  0x00000000006d3a35 in ExplainExecuteQuery (execstmt=0x16370a0, into=0x0, es=0x1744b70, queryString=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');",  params=0x0, queryEnv=0x0) at prepare.c:642
#7  0x00000000006a6807 in ExplainOneUtility (utilityStmt=0x16370a0, into=0x0, es=0x1744b70, queryString=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');",  params=0x0, queryEnv=0x0) at explain.c:486
#8  0x00000000006a62da in ExplainOneQuery (query=0x1637368, cursorOptions=2048, into=0x0, es=0x1744b70,  queryString=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');", params=0x0, queryEnv=0x0) at explain.c:375
#9  0x00000000006a5f8b in ExplainQuery (pstate=0x1658dc0, stmt=0x16370d8, params=0x0, dest=0x1658d28) at explain.c:281
#10 0x00000000009935b5 in standard_ProcessUtility (pstmt=0x16375f0, queryString=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');", readOnlyTree=false,  context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x1658d28, qc=0x7ffc0dc5c9b0) at utility.c:870
#11 0x0000000000992d3e in ProcessUtility (pstmt=0x16375f0, queryString=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');", readOnlyTree=false,  context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x1658d28, qc=0x7ffc0dc5c9b0) at utility.c:530
#12 0x0000000000991947 in PortalRunUtility (portal=0x16d6250, pstmt=0x16375f0, isTopLevel=true, setHoldSnapshot=true, dest=0x1658d28, qc=0x7ffc0dc5c9b0) at pquery.c:1158
#13 0x00000000009916b3 in FillPortalStore (portal=0x16d6250, isTopLevel=true) at pquery.c:1031
#14 0x000000000099101c in PortalRun (portal=0x16d6250, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x16376e0, altdest=0x16376e0, qc=0x7ffc0dc5cb80) at pquery.c:763
#15 0x000000000098ac9f in exec_simple_query (query_string=0x1636510 "explain analyze execute p1('2006-04-05', '2006-04-20');") at postgres.c:1250
#16 0x000000000098f1e0 in PostgresMain (dbname=0x16620d8 "postgres", username=0x16620b8 "mingjie") at postgres.c:4593
#17 0x00000000008cc052 in BackendRun (port=0x1658840) at postmaster.c:4511
#18 0x00000000008cb9eb in BackendStartup (port=0x1658840) at postmaster.c:4239
#19 0x00000000008c7fe8 in ServerLoop () at postmaster.c:1806
#20 0x00000000008c78ba in PostmasterMain (argc=1, argv=0x1630110) at postmaster.c:1478
#21 0x00000000007cdaff in main (argc=1, argv=0x1630110) at main.c:202

ExecInitAppend函数会根据优化器记录的信息,node->part_prune_info:
在这里插入图片描述
来对执行计划进行运行时剪枝:ExecInitPartitionPruning

从上图part_prune_info的结构来看,运行是剪枝和优化器剪枝用的是一套逻辑,都是先走prune step,最后combine,详见上一篇。

问题二:为什么Generic Plan不能剪枝?

Generic Plan是不太参数的计划,也就是只能靠

prepare p1 (date, date) as select * from measurement where logdate between $1 and $2;

生成计划,无法拿到参数也就无法剪枝了。

代码上有什么区别呢?

对比下prune_append_rel_partitions的执行流程区别:

prepare p1 (date, date) as select * from measurement where logdate between $1 and $2;
explain analyze execute p1('2006-04-05', '2006-04-20');

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/29093.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg音视频处理工具介绍及应用

1 FFmpeg介绍 FFmpeg项目由 Fabrice Bellard在2000年创立。到目前为止&#xff0c;FFmpeg项目的开发者仍然与VLC、MPV、dav1d、x264等多媒体开源项目有着广泛的重叠。Ffmpeg&#xff08;FastForward Mpeg&#xff09;是一款遵循GPL的开源软件&#xff0c;在音视频处理方面表现…

UDS关于0x37服务退出传输学习笔记

1.服务说明 客户端使用此服务来终止客户端和服务器之间的数据传输&#xff08;上传或下载&#xff09;。 2.请求消息 2.1请求消息子功能参数$Level&#xff08;LEV_&#xff09;定义 此服务不使用子函数参数。 2.2请求消息数据参数定义 transferRequestParameterRecord&a…

《微服务实战》 第二十九章 分布式事务框架seata AT模式

前言 本章节介绍微服务分布式项目中&#xff0c;使用的事务框架seata。 官网&#xff1a;http://seata.io/zh-cn/ springcloud-nacos-seata&#xff1a;https://github.com/seata/seata-samples/tree/master/springcloud-nacos-seata 1、概念 Seata 是一款开源的分布式事务解…

使用docker快速搭建redis哨兵模式

说明 本文主要参考&#xff1a; https://www.cnblogs.com/coderaniu/p/15352323.html https://developer.aliyun.com/article/892805 但是这两篇博客均缺失部分关键性细节&#xff0c;所以重新撰文。读者可以结合本文和上述文章一起阅读。 安装步骤 安装docker和docker-co…

小作文--流程图(练习1)

【【雅思写作】带你打破小作文‘流程图’的传说】 https://www.bilibili.com/video/BV1QP411Q7Gh/?share_sourcecopy_web&vd_source78768d4ae65c35ff26534bbaa8afc267 雅思小作文-流程图, 看这一篇就够了! - 冯凯文的文章 - 知乎 https://zhuanlan.zhihu.com/p/35868880 …

算法模板(3):搜索(3):图论提高

图论提高 最小生成树 &#xff08;1&#xff09;朴素版prim算法&#xff08; O ( n 2 ) O(n ^ 2) O(n2)&#xff09; 适用范围&#xff1a;稠密图易错&#xff1a;注意有向图还是无向图&#xff1b;注意有没有重边和负权边。从一个集合向外一个一个扩展&#xff0c;最开始只…

记录基于Vue.js的移动端Tree树形组件

目录 一、Liquor Tree 入门 &#xff1a; Development Component Options 组件选项 Structure 结构 二、vue-treeselect Introduction 介绍 Getting Started 入门 Vue 树形选择器&#xff08; Vue tree select &#xff09;组件在搭建 Vue 的 app 中特别常用&#xff0…

【Java|golang】2611. 老鼠和奶酪

有两只老鼠和 n 块不同类型的奶酪&#xff0c;每块奶酪都只能被其中一只老鼠吃掉。 下标为 i 处的奶酪被吃掉的得分为&#xff1a; 如果第一只老鼠吃掉&#xff0c;则得分为 reward1[i] 。 如果第二只老鼠吃掉&#xff0c;则得分为 reward2[i] 。 给你一个正整数数组 reward1…

【TypeScript】枚举类型和泛型的详细介绍

目录 TypeScript枚举类型 TypeScript泛型介绍 &#x1f3b2;泛型的基本使用 &#x1f3b2;泛型接口的使用 &#x1f3b2;泛型类的使用 &#x1f3b2;泛型的类型约束 枚举类型 枚举类型是为数不多的TypeScript特有的特性之一, JavaScript是没有的&#xff1a; 枚举其实就…

【FPGA零基础学习之旅#8】阻塞赋值与非阻塞赋值讲解

&#x1f389;欢迎来到FPGA专栏~阻塞赋值与非阻塞赋值 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家…

解决elementUI弹出框关闭后再打开el-select下拉框无法选中的问题

文章目录 一、问题描述&#xff1a;二、问题解决 一、问题描述&#xff1a; 使用的前端UI框架为elementUI。 el-select组件在一个弹框中&#xff0c;打开该弹框&#xff0c;el-select可以正常选中&#xff0c;但是保存弹框中的表单信息关闭弹框后&#xff0c;再打开弹框&…

Spark大数据处理讲课笔记4.1 Spark SQL概述、数据帧与数据集

零、本讲学习目标 了解Spark SQL的基本概念掌握DataFrame的基本概念掌握Dataset的基本概念会基于DataFrame执行SQL查询 在很多情况下&#xff0c;开发工程师并不了解Scala语言&#xff0c;也不了解Spark常用API&#xff0c;但又非常想要使用Spark框架提供的强大的数据分析能力…

物联网Lora模块从入门到精通(二) LED灯泡闪烁与呼吸灯

目录 一、前言 二、实践与代码 1.电亮LED1 2.熄灭LED1 3.翻转LED电平 4.LED1与LED2交替闪烁 5.LED1呼吸灯 三、程序代码 一、前言 本篇内容属于新大陆物联网Lora模块开发&#xff0c;使用给定的Lora基础例程&#xff0c;并在其基础上开发完成&#xff0c;并可为其他版本的Lo…

亚马逊云科技Serverless构建的实时数仓解决方案,助力猎豹降低30%成本

也许你也听过这样一句话&#xff1a;“21世纪什么最贵&#xff1f;人才&#xff01;”当数字经济全面席卷而来&#xff0c;这个问题的答案不可置否地变为了“数据”。通过数据分析获取近乎实时的洞察&#xff0c;以驱动业务的全流程&#xff0c;是企业数字化转型的必经之路。借…

Linux操作系统学习——启动

概要 Linux操作系统内核是服务端学习的根基&#xff0c;也是提高编程能力、源码阅读能力和进阶知识学习能力的重要部分&#xff0c;本文开始将记录Linux操作系统中的各个部分源码学习历程。 1. 理解代码的组织结构 以Linux源码举例&#xff0c;首先你得知道操作系统分为哪几个部…

【SpringCloud入门】-- 初识Eureka注册中心

目录 1.SpringCloudEureka简介 2.什么是CAP原则&#xff1f; 3.注册中心的概念&#xff1f; 4.SpringCloud其他注册中心 5.搭建Eureka注册中心 6.eureka的配置(主要是server&#xff0c;instance&#xff0c;client) 7.eureka集群概念 8.eureka集群搭建 1.SpringCloudE…

基于R语言的物种气候生态位动态量化与分布特征模拟

目录 专题一 引言 专题二 数据获取与处理方法 专题三 组合物种分布模型&#xff08;Ensemble Species Distribution Model&#xff09;的原理与使用 专题四 拓展研究 专题五 结果分析与论文写作 专题六 案例分析 专题七 总结和展望 利用R语言进行物种气候生态位动态量化…

【蓝桥杯算法题】用java遍写税收计算

【蓝桥杯算法题】用java遍写税收计算 题目&#xff1a;劳务报酬税收计算&#xff1a;输入 m &#xff0c;输出税后收入。如果 m <800&#xff0c;不扣税&#xff0c; 如果800< m <4000&#xff0e;则 m 减去800后的金额扣除20&#xff05;所得税。如果 m >4000&…

【计算机网络详解】——运输层(学习笔记)

&#x1f4d6; 前言&#xff1a;两台主机的通信&#xff0c;实际上两台主机中的应用进程进行通信&#xff0c;而在一台计算机中&#xff0c;用不同的端口号标识不同的应用进程。本节将介绍传输层的相关内容&#xff0c;包括端口号的分配方法、端口号的复用与分用、以及传输层的…

编译tolua——3、以pbc为例子,添加第三方库

目录 1、编译工具和环境说明 2、基础编译tolua 3、以pbc为例子&#xff0c;添加第三方库 4、更新luaJit 大家好&#xff0c;我是阿赵。 之前分享过怎样正常编译基础版本的tolua。这次用添加pbc为例&#xff0c;看看怎样往tolua里面添加其他的第三方库。知道了方法之后&#xf…