postgresql-重复执行相同语句,试试 prepare!
文章目录
每次你向 PostgreSQL 发送 SQL 语句时,数据库都必须对其进行解析(parse)。解析虽然很快,但如果同样的语句被解析一千次,这种操作累积起来可能会占用大量时间,而这些时间本可以用于处理其他事务。为避免这种情况,PostgreSQL 提供了 prepare 语句。通过使用它,你可以避免重复解析语句,数据库只需执行planning和execution操作。
为了生成一些示例数据,这里使用了scale factor(规模因子)为 100 的 pgbench,这在 pgbench_accounts 表中产生10,000,000 行:
bench=#pgbench -U dbmgr -h 127.0.0.1 -p 5432 -i -s 100 bench
Password:
dropping old tables...
NOTICE: table "pgbench_accounts" does not exist, skipping
NOTICE: table "pgbench_branches" does not exist, skipping
NOTICE: table "pgbench_history" does not exist, skipping
NOTICE: table "pgbench_tellers" does not exist, skipping
creating tables...
generating data (client-side)...
10000000 of 10000000 tuples (100%) done (elapsed 19.54 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done in 29.01 s (drop tables 0.00 s, create tables 0.02 s, client-side generate 20.19 s, vacuum 0.70 s, primary keys 8.09 s).
postgres@pgrec-d:~psql bench
psql (15.5 (Ubuntu 15.5-1.pgdg22.04+1))
Type "help" for help.bench=# select count(*) from pgbench_accounts;count
----------10000000
(1 row)bench=# d pgbench_accountsTable "public.pgbench_accounts"Column | Type | Collation | Nullable | Default
----------+---------------+-----------+----------+---------aid | integer | | not null | bid | integer | | | abalance | integer | | | filler | character(84) | | |
Indexes:"pgbench_accounts_pkey" PRIMARY KEY, btree (aid)
简单query一下:
bench=# select count(*) from pgbench_accounts where aid = 11111;count
-------1
(1 row)
正如本文开头所述,PostgreSQL 将需要解析该语句。使用带有正确选项的 explain,您可以看到产生执行计划花费了多少时间:
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------Aggregate (cost=4.46..4.46 rows=1 width=8) (actual time=0.041..0.042 rows=1 loops=1)Buffers: shared hit=4-> Index Only Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.43..4.45 rows=1 width=0) (actual time=0.030..0.032 rows=1 loops=1)Index Cond: (aid = 11111)Heap Fetches: 0Buffers: shared hit=4Planning Time: 0.125 msExecution Time: 0.086 ms
(8 rows)
产生此语句的执行计划比执行它花费更多时间。现在假设您要执行同一条语句一千次:
bench=#\t
bench=#select 'select count(*) from pgbench_accounts where aid = 11111;' from generate_series(1,1000) i; \g test.sql
bench=# \! cat test.sql | head
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
select count(*) from pgbench_accounts where aid = 11111;
...
当执行该命令时,强制 PostgreSQL解析所有这 1000 条语句:
bench=# \timing
Timing is on.
bench=#\! /usr/bin/time -p psql -U dbmgr -f test.sql -d bench
real 0.76s
user 0.13s
sys 0.1s
为了避免这种情况,我们使用prepare去准备这条sql:
prepare c1 as select count(*) from pgbench_accounts where aid = 11111;
PREPARE
一旦prepare好,就可以执行它:
bench=# execute c1;count
-------1
(1 row)
explain:
bench=# explain(analyze,buffers) execute c1;Aggregate (cost=4.46..4.46 rows=1 width=8) (actual time=0.041..0.042 rows=1 loops=1)Buffers: shared hit=4-> Index Only Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.43..4.45 rows=1 width=0) (actual time=0.030..0.032 rows=1 loops=1)Index Cond: (aid = 11111)Heap Fetches: 0Buffers: shared hit=4Planning Time: 0.007 msExecution Time: 0.100 ms
注意,与未准备好的语句相比,planning time减少了不少:
bench=# explain(analyze,buffers) select count(1) from pgbench_accounts where aid=11111;Aggregate (cost=4.46..4.46 rows=1 width=8) (actual time=0.076..0.077 rows=1 loops=1)Buffers: shared hit=4-> Index Only Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.43..4.45 rows=1 width=0) (actual time=0.057..0.059 rows=1 loops=1)Index Cond: (aid = 11111)Heap Fetches: 0Buffers: shared hit=4Planning:Buffers: shared hit=3Planning Time: 0.376 msExecution Time: 0.166 ms
当现在这样执行一千次:
bench=# \t
Tuples only is off.
bench=# select 'execute c1;' from generate_series(1,1000) i; \g test.sql
bench=# \! sed -i '1s/^/prepare c1 as select count(*) from pgbench_accounts where aid = 11111;/' test.sql
bench=# \! /usr/bin/time -p psql -U dbmgr -f test.sql -d bench
real 0.55s
user 0.11s
sys 0.15s
执行时间将会缩短。在这个简单的例子中,效果不太明显,但这是因为语句本身非常简单。顺便提一下,预编译的语句只在会话期间有效,所以 sed 命令将 prepare 语句添加到文件顶部,预编译本身也需要时间。如果不预编译,执行时间会更短。
当 where 子句中的值发生变化时,可以这样做:
bench=# prepare c1 as select count(*) from pgbench_accounts where aid = $1;
PREPARE
Time: 0.387 ms
解除prepare好的语句
bench=# deallocate c1;
DEALLOCATE
Time: 0.336 ms
相关文章:
postgresql-重复执行相同语句,试试 prepare!
文章目录 每次你向 PostgreSQL 发送 SQL 语句时,数据库都必须对其进行解析(parse)。解析虽然很快,但如果同样的语句被解析一千次,这种操作累积起来可能会占用大量时间,而这些时间本可以用于处理其他事务。为避免这种情况ÿ…...
wpf加载带材料的3D模型(下载的3D预览一样有纹理)
背景:最近真的是忙啊,累出汁水了 整体效果: 放大可以看清砖头: 1、需要自己准备好3D模型,比如我这里是下载的这里的3D Warehouse,下载Collada File格式文件 2、解压可以看到一个model.dae和材料的文件夹&…...
【k8s之深入理解调度】调度框架扩展点理解
参考自 K8s 调度框架设计与 scheduler plugins 开发部署示例(2024) 调度插件扩展点 等待调度阶段PreEnqueuePod 处于 ready for scheduling 的阶段。 内部工作原理:sig-scheduling/scheduler_queues.md。在 Pod 被放入调度队列之前执行的插…...
音视频基础理论
1. 音频基础 1.1 音频基本概念 1.1 频率:声波的频率,即声音的音调,人类听觉的频率(音调)范围为20Hz--20KHz 1.2 振幅:即声波的响度,通俗的讲就是声音的高低,一般男生的声音振幅(响度)大于女生。 1.3 波形…...
《江苏科技大学学报(自然科学版)》
《江苏科技大学学报(自然科学版)》(双月刊,国内外公开发行)是由江苏省教育厅主管、江苏科技大学主办的理工类学术期刊,1986年创刊,国际刊号:ISSN1673-4807,国内刊号&…...
C++初学者指南-5.标准库(第二部分)–随机数生成
C初学者指南-5.标准库(第二部分)–随机数生成 文章目录 C初学者指南-5.标准库(第二部分)–随机数生成基本概念例子统一随机数布尔值(“抛硬币”)正态分布具有独立概率的整数 怎么做种子引擎使用自定义生成器 shuffle算法分布类型概述通用接口均匀分布采样…...
Unity2017在安卓下获取GPS位置时闪退的解决办法
在Unity使用低功耗蓝牙通信(BLE)需要用到设备的位置信息。但是调用Input.location.Start()程序会闪退。 解决办法:调用原生安卓接口。 参见《Unity2021通过aar调用Android方法》编写一个aar插件gpsplugin,在插件中提供获取GPS位…...
OpenGL ES 索引缓冲区(4)
OpenGL ES 索引缓冲区(4) 简述 本节会介绍索引缓冲区,索引缓冲区和顶点缓冲区类似,也是显存上的一段内存,只不过上面的数据用处不同,索引缓冲区故名思义里面的数据是用于索引,主要作用是用于复用顶点缓冲区里的数据。…...
01:(寄存器开发)点亮一个LED灯
寄存器开发 1、单片机的简介1.1、什么是单片机1.2、F1系列内核和芯片的系统架构1.3、存储器映像1.4、什么是寄存器 2、寄存器开发模板工程3、使用寄存器点亮一个LED4、代码改进15、代码改进2 本教程使用的是STM32F103C8T6最小系统板,教程来源B站up“嵌入式那些事”。…...
.Net 6.0 Windows平台如何判断当前电脑是否联网
最近在工作中开发需要判断当前电脑是否联网的需求,在网上找了一个调用window API来判断本机是否联网。具体请看下面介绍: 1.方法一(调用winAPI) [DllImport("wininet")] public static extern bool InternetGetConnec…...
微软准备了 Windows 11 24H2 ISO “OOBE/BypassNRO“命令依然可用
Windows 11 24H2 可能在未来几周内开始推出。 微软已经要求 OEM 遵循新的指南准备好 Windows 11 24H2 就绪的驱动程序,并且现在已经开始准备媒体文件 (.ISO)。 OEM ISO 的链接已在微软服务器上发布。 一个标有"X23-81971_26100.1742.240906-0331.ge_release_sv…...
MacOS 终端执行安装 Brew
在配置新的 Mac 环境时,如果你发现终端中无法识别 brew 命令,可以按照以下步骤进行解决。 步骤 1:确保网络稳定 为了避免安装过程中出现中断,建议使用 Wi-Fi 或有线连接,不推荐使用移动网络。 步骤 2:打…...
【设计模式-解释模式】
定义 解释器模式是一种行为设计模式,用于定义一种语言的文法,并提供一个解释器来处理该语言的句子。它通过为每个语法规则定义一个类,使得可以将复杂的表达式逐步解析和求值。这种模式适用于需要解析和执行语法规则的场景。 UML图 组成角色…...
51单片机应用开发(进阶)---数码管+按键+蜂鸣器(电磁炉显示模拟)
实现目标 1、加强数码管、按键的学习,实现数码显示变量数据(四位数的显示); 2、4位数码2个按键无源蜂鸣器实现模拟电磁炉功率调节及显示; 一、内容描述 功能描述:1、开机显示电磁炉功率300,每…...
Emergency Stop (ES)
文章目录 1. 介绍2. Feature List3. 紧急停止信号触发方式3.1 Port触发紧急停止信号3.2 SMU事件触发紧急停止信号3.3 软件触发紧急停止信号 4. 应用场景4.1 Port4.2 MSC 1. 介绍 Emergency Stop (ES)是Ifx System Control Units (SCU)六大模块之一。详细信息可以参考Infineon-…...
[C++][第三方库][gtest]详细讲解
目录 1.介绍2.安装3.使用1.头文件包含2.框架初始化接口3.调用测试样例4.TEST宏5.断言宏6.示例 1.介绍 gtest是一个跨平台的C单元测试框架,由Google公司发布gtest是为了在不同平台上为编写C单元测试而生成的,它提供了丰富的断言、致命和非致命判断、参数…...
【Java数据结构】 链表
【本节目标】 1. ArrayList 的缺陷 2. 链表 3. 链表相关 oj题目 一. ArrayList的缺陷 上节课已经熟悉了ArrayList 的使用,并且进行了简单模拟实现。通过源码知道, ArrayList 底层使用数组来存储元素: public class ArrayList<E>…...
前端——Ajax和jQuery
一、Ajax Ajax即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML), 通过 JS 异步的向服务器发送请 求并接收响应数据。 同步访问:当客户端向服务器发送请求时,服务器在处理的过程中,浏览器…...
C++-vector模拟实现
###vector底层相当于是数组,查看源码可以发现,这个类的私有成员变量是三个迭代器;在实现时迭代器就可以当作是vector里面的元素的指针类型; ###vector是一个类模板,实现时也应当按照这样的写法用一个模板去实现&#…...
Activity
69[toc] 1.启停活动页面 1.Activity启动和结束 从当前页面跳到新页面 startActivity(new Intent(this, ActFinishActivity.class));从当前页面返回上一个页面,相当于关闭当前页面 finish();2.Activity生命周期 官方描述生命周期 onCreate:创建活…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
