postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析
前言
最近这段时间一直使用pg 数据库插入更新大量的数据,发现pg数据库有时候插入数据非常慢,这里我对此问题作出分析,找到一部分原因,和解决办法。
一 死元祖过多
提起pg数据库,由于他的构造,就不得不说他的元祖。
1.1 什么是元祖?
在Postgresql做delete操作时,数据集(也叫做元组 (tuples))是没有立即从数据文件中移除的,仅仅是通过在行头部设置xmax做一个删除标记。update操作也是一样的,在postgresql中可以看作是先delete再insert;
这是Postgresql MVCC的基本思想之一,因为它允许在不同进程之间只进行最小的锁定就可以实现更大的并发性。这个MVCC实现的缺点当然是它会留下被标记删除的 元组( dead tuples),即使在这些版本的所有事务完成之后。
1.2 死元祖过多的危害
如果不清理掉那些dead tuples(对任何事务都是不可见的)将会永远留在数据文件中,浪费磁盘空间,对于表来说,有过多的删除和更新,dead tuples很容易占绝大部分磁盘空间。而且dead tuples也会在索引中存在,更加加重磁盘空间的浪费。这是在PostgreSQL中常说的膨胀(bloat)。自然的,需要处理的数据查询越多,查询的速度就越慢。
1.3 查询死元祖情况
1.3.1 查询那些表的死元祖过多
1、查询当前数据库表已经达到自动清理条件的表及相关信息
SELECT
c.relname 表名,
(current_setting('autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples AS 自动分析阈值,
(current_setting('autovacuum_vacuum_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_vacuum_scale_factor')::NUMERIC(12,4))*reltuples AS 自动清理阈值,
reltuples::DECIMAL(19,0) 活元组数,
n_dead_tup::DECIMAL(19,0) 死元组数
FROM
pg_class c
LEFT JOIN pg_stat_all_tables d
ON C.relname = d.relname
WHERE
c.relname LIKE'tb%' AND reltuples > 0
AND n_dead_tup > (current_setting('autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples;
2、查询当前正在进行自动清理的表及相关信息
SELECT
c.relname 对象名称,
l.pid 进程id,
psa.STATE 查询状态,
psa.query 执行语句,
now( ) - query_start 持续时间
FROM
pg_locks l
INNER JOIN pg_stat_activity psa ON ( psa.pid = l.pid )
LEFT OUTER JOIN pg_class C ON ( l.relation = C.oid )
WHERE psa.query like 'autovacuum%' and l.fastpath='f'
ORDER BY query_start asc;
3、查询自动清理的历史统计信息
SELECT
relname 表名,
seq_scan 全表扫描次数,
seq_tup_read 全表扫描记录数,
idx_scan 索引扫描次数,
idx_tup_fetch 索引扫描记录数,
n_tup_ins 插入的条数,
n_tup_upd 更新的条数,
n_tup_del 删除的条数,
n_tup_hot_upd 热更新条数,
n_live_tup 活动元组估计数,
n_dead_tup 死亡元组估计数,
last_vacuum 最后一次手动清理时间,
last_autovacuum 最后一次自动清理时间,
last_analyze 最后一次手动分析时间,
last_autoanalyze 最后一次自动分析时间,
vacuum_count 手动清理的次数,
autovacuum_count 自动清理的次数,
analyze_count 手动分析此表的次数,
autoanalyze_count 自动分析此表的次数,
( CASE WHEN n_live_tup > 0 THEN n_dead_tup :: float8 / n_live_tup :: float8 ELSE 0 END ) :: NUMERIC ( 12, 2 ) AS "死/活元组的比例"
FROM
pg_stat_all_tables
WHERE
schemaname = 'public'
ORDER BY n_dead_tup::float8 DESC;
1.4 解决办法
1.4.1 修改参数,提高效率

1.4.2 手动清理
有时候自动清理往往会因为各种原因实际效果达不到预期,这时候我们需要对某些死元祖过多的表进行手动清理
VACUUM FULL VERBOSE 模式名.表名;
VACUUM FULL VERBOSE ANALYZE 模式名.表名;
二 索引过多导致插入过慢
索引过多,虽会提高查询速度,但是插入数度就很慢,在大数据插入前最好能看一下表的索引。如果索引过多,建议删掉,插入或者更新数据后,再重新建索引。
查询索引:
select * from pg_indexes where tablename='表名';
三 触发器
如果一张表有触发器,你往上插入数据就会非常慢。所以要删除后插入在创建
1.查看触发器 :
SELECT * FROM pg_trigger;
2.查询某个表的触发器
SELECT event_object_table
,trigger_name
,event_manipulation
,action_statement
,action_timing
FROM information_schema.triggers
WHERE event_object_table = '表名'
ORDER BY event_object_table
,event_manipulation;
四 死锁
数据插入慢或者停滞不前有可能是 死锁。
1 查询等待与锁的进程、语句等信息
select w1.pid as 等待进程,
w1.mode as 等待锁模式,
w2.usename as 等待用户,
w2.query as 等待会话,
b1.pid as 锁的进程,
b1.mode 锁的锁模式,
b2.usename as 锁的用户,
b2.query as 锁的会话,
b2.application_name 锁的应用,
b2.client_addr 锁的IP地址,
b2.query_start 锁的语句执行时间
from pg_locks w1
join pg_stat_activity w2 on w1.pid=w2.pid
join pg_locks b1 on w1.transactionid=b1.transactionid and w1.pid!=b1.pid
join pg_stat_activity b2 on b1.pid=b2.pid
where not w1.granted;
2.杀死造成锁的进程
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid='62560'
postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析的更多相关文章
- MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解
本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍,需要的朋友参考下 MySQL数据库insert和update语句引:用于操作数 ...
- 转载:MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解
转自:http://www.jb51.net/article/39199.htm 本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍, ...
- SQL中使用UPDATE更新数据时一定要记得WHERE子句
我们在使用 SQL 中的 UPDATE 更新数据时,一般都不会更新表中的左右数据,所以我们更新的数据的 SQL 语句中会带有 WHERE 子句,如果没有WHERE子句,就回更新表中所有的数据,在 my ...
- SQL Server扩展事件的使用ring_buffer target时“丢失”事件的原因分析以及ring_buffer target潜在的问题
事情起因: 排查SQL Server上的死锁问题,一开始想到的就是扩展事件, 第一种方案,开profile守株待兔吧,显得太low了,至于profile的变种trace吧,垂垂老矣,也一直没怎么用过. ...
- 数据库insert和update
1.当使用insert时不能使用where id=?,这是要使用update语句 2.只对一些列插入数据或者更新数据: insert是: insert tb(column1,column2..)val ...
- 关于web程序中使用KindEditor向数据库插入带有格式的数据时出现的问题
最近做一个项目,需要对输入的文字在存入数据库之前进行文本格式编辑,于是我用到了KindEditor,当然怎么用在asp.net页面中,这里就不过多叙述了. 主要是遇到在将赋予格式的文本插入数据库时遇到 ...
- MySQL数据库导入或者同步大量数据时数据丢失解决方案
相信大家都经常遇到这样的情况,我们在编码的过程中经常需要在调试代码的时候切换到本地的数据库上做修改调试,如果当测试数据库的数据在几十万或者上百万数据的时候,我们无论是通过恢复备份/导入SQL的方式来把 ...
- 如何优化用SQL语句INSERT INTO … SELECT插入数据时锁全表的问题
1.binlog format 启用Row Based Replication(行复制)模式: SET GLOBAL binlog_format = 'ROW'; 如果你想永久的启用这个模式,请修改m ...
- 提取postgresql数据库中jsonb列的数据
; SELECT t.errmsg,sms_records.* FROM sms_records, jsonb_to_record(result_json) AS t(errmsg text,sid ...
- eval函数解析json数据时加上圆括号的原因
var temp = eval("(" + data + ")"); //解析json数据 json是以”{}”的方式来开始以及结束的,在JS中,“{}”会被当 ...
随机推荐
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(36)-掌握Fiddler中Fiddler Script用法,你会有多牛逼-上篇
1.简介 Fiddler是一款强大的HTTP抓包工具,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有 ...
- conan环境安装
环境 安装conan 使用conan 搜索包 导入包 编译 打包项目 准备源码 编译成conan包 环境 ubuntu:bionic的docker image docker run -it ubunt ...
- ARL灯塔系统搭建
前言 ARL(Asset Reconnaissance Lighthouse)资产侦查灯塔,是一个良好的资产收集系统,旨在为渗透测试人员以及安全团队基于企业的网络安全能快速查找到指定企业资产中的脆弱点 ...
- 终于定制出顺手的Obsidian斜杠命令
wolai.语雀.思源笔记等笔记软件,有一个特别好用的功能,通过斜杠打开快速输入面板,让我们快速输入markdown.插入图片外链.插入文件.插入iframe等,十分方便. 但当我使用obsidian ...
- 关于jQuery的操作
jQuery简介 简化了JS 类似于 后端 JDBC(操作数据库的基本API) dbutils(封装JDBC) xxx.jar 前端 JS ...
- Azure DevOps 的架构窥探
工作的缘故,接触 TFS (Team Foundation Server)挺多的,现在改名为 Azure DevOps,分为 可私有化部署版本 Azure DevOps Server,简称ADS,以及 ...
- c#5.0(.net 4.5之后)的 Async+await+Task的异步机制的调试笔记
1.)无返回值的情况(异步也是基于线程). using System; using System.Collections.Generic; using System.Linq; using Syste ...
- 使用 Helm 安装 MQTT 服务器-EMQX
EMQX ️ Info: 使用 EMQX 通过 Helm3 在 Kubernetes 上部署 EMQX 4.0 集群 | EMQ emqx/deploy/charts/emqx at main-v4. ...
- [OpenCV实战]8 深度学习目标检测网络YOLOv3的训练
目录 1 数据集 1.1 下载openImages雪人数据[约1.5小时] 1.2 训练集测试集拆分 2 Darknet 2.1 下载并构建Darknet 2.2 修改代码以定期保存模型文件 2.3 ...
- JavaFx 页面和控件设置快捷键
原文:JavaFx 页面和控件设置快捷键 - Stars-One的杂货小窝 之前说过一篇window系统全局快捷键的设置,本期主要是讲解JavaFx应用程序的快捷键设置,还是有所区别的 这里主要是To ...