往期分享
IO基本概念
- IO,就是对磁盘进行读写的动作。
- IO延时,一个IO操作的执行时间。
- 逻辑IO,由应用程序发给文件系统的IO。
- 物理IO,由文件系统发给磁盘的IO。
- 顺序IO,顺序的从磁盘进行读写动作。
- 随机IO,随机的访问磁盘进行读写操作。
- 同步写,需要等数据完全写入磁盘进行返回。
- 异步写,无需等待数据写入磁盘进行返回,释放CPU资源。
IO高的常见原因
SQL扫描行高
查看资源监控的数据盘IOPS
可以发现基本都是读占用的,一般客户端SQL访问的数据都是从数据库共享缓冲区进行返回,如果数据未在共享缓冲区命中就会需要从磁盘中进行读取,读的IOPS比较高,说明大量的从磁盘读取数据到数据库共享缓冲区中,可能存在SQL扫描行较高的情况。
查看引擎监控
发现全表扫描行明显增加,说明客户端读取了大量的数据。
查看性能洞察
可以找到对应的问题SQL,可以对问题SQL进行索引优化或者增加规格承担更高的负载。
导入数据
查看资源监控的数据盘IOPS
从图中可以看出有大量的写入IOPS,怀疑存在大量的数据导入动作。
查看das中的性能洞察可以发现是由该操作导致的IOPS升高
尽量避免高峰期的数据导入动作。
Vacuum操作
vacuum指的是PostgreSQL需要对垃圾数据进行清理动作,一般update和delete过程,数据表会产生垃圾数据造成膨胀,需要及时通过vacuum进行清理回收空间。
查看资源监控的数据盘IOPS
此时可以看到IOPS中读写都占用了较多的资源。
查看引擎监控操作行数
此时发现操作行数没有明显增加,此时可以怀疑是vacuum或者CheckPoint引起的IOPS升高,通过查询pg_stat_progress_vacuum可以查看当前正在运行vacuum的动作及vacuum的进度。可以确定是由vacuum引起的IOPS升高。
postgres=# select * from pg_stat_progress_vacuum ; -[ RECORD 1 ]------+-------------- pid | 109229 datid | 13593 datname | postgres relid | 40435 phase | scanning heap heap_blks_total | 943453 heap_blks_scanned | 937101 heap_blks_vacuumed | 0 index_vacuum_count | 0 max_dead_tuples | 291 num_dead_tuples | 0
通过pg_stat_user_tables也可以查看历史vacuum的情况
postgres=# select * from pg_stat_user_tables where relname ='t_all'; -[ RECORD 1 ]-------+------------------------------ relid | 40435 schemaname | public relname | t_all seq_scan | 4547 seq_tup_read | 35959634448 idx_scan | idx_tup_fetch | n_tup_ins | 91514896 n_tup_upd | 0 n_tup_del | 0 n_tup_hot_upd | 0 n_live_tup | 91514896 n_dead_tup | 0 n_mod_since_analyze | 0 last_vacuum | 2020-11-20 14:25:19.077927+08 last_autovacuum | last_analyze | last_autoanalyze | 2020-11-20 11:59:34.641906+08 vacuum_count | 1 autovacuum_count | 0 analyze_count | 0 autoanalyze_count | 5
对于vacuum引起的IO升高可以通过调整vacuum相关参数进行降低vacuum对IO产生的影响。
autovacuum_vacuum_cost_delay指的是vacuum动作代价达到autovacuum_vacuum_cost_limit时vacuum进程休息的时间单位是ms。autovacuum_vacuum_cost_limit指的是vacuum进程代价评估的阈值。通过这两个参数调整可以很大程度降低vacuum操作对于生成环境IO的影响,同时也需要考虑vacuum回收速度慢也会导致表膨胀的更加严重。
CheckPoint
CheckPoint指的是将数据库共享缓冲区的脏页进行写入到磁盘的操作,一般该行为由四种条件触发
- 定时触发,通过checkpoint_timeout参数定时将将数据库共享缓冲区的脏页进行写入到磁盘,此行为为异步写,数据分多次小批量写入磁盘,对IO影响小。
- wal日志写入量达到max_wal_size触发,wal日志是循环使用的,当日志量达到max_wal_size,会触发积极的CheckPoint,此行为为同步写,会全速进行数据写入动作,对IO影响大。
- 手动CheckPoint,此行为为同步写,会全速进行数据写入动作,对IO影响大。
- 重启实例,此行为为同步写,会全速进行数据写入动作,对IO影响大。
目前对于这种情况可以通过查询pg_stat_bgwriter分析,checkpoints_timed指的是定时触发的次数,checkpoints_req指的是手动触发以及wal日志写入量达到max_wal_size触发,如果checkpoints_req高需要关注是否有大批量导入的情况,可以控制批量导入的大小,最好调整为小批量,多批次导入。
postgres=# select * from pg_stat_bgwriter ; -[ RECORD 1 ]---------+------------------------------ checkpoints_timed | 8271 checkpoints_req | 160 checkpoint_write_time | 9109283 checkpoint_sync_time | 22878 buffers_checkpoint | 1228674 buffers_clean | 829714 maxwritten_clean | 293 buffers_backend | 3731358 buffers_backend_fsync | 0 buffers_alloc | 2290169 stats_reset | 2020-06-28 15:32:00.021466+08