暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL性能优化:性能诊断工具pg_profile

10年+资深DBA&数据库架构师; OpenGauss技术布道专家; PG/MySQL内核技术推广者; 著有《Oracle高性能自动化运维》; 拥有多个国产数据库官方认证; 致力于开源MySQL/PG技术推广/国产信创交付落地以及最佳实践探索; 个人公众号:dba悠然。


一、pg_profile用途
pg_profile基于postgres标准统计视图,通过捕获数据库中被任意服务器进程执行的命令、收集关于表和索引访问的统计信息、监控对块读写次数、对用户定义函数使用的跟踪等四个方面来进行性能分析汇总展示。它类似于Oracle AWR架构,指定时间间隔生成快照,并提供html文档进行分析。

二、安装部署

1.依赖extension
pg_profile需要使用dblink和pg_stat_statements扩展插件,pg数据库自带插件,不需要额外下载编译。

2.安装部署
2.1安装pg_profile驱动
//postgres用户:
tar -zxvf pg_profile—0.3.6.tar.gz
cp pg_profile* usr/local/pgsq/share/extension
2.2配置参数

  1. vi postgresql.conf

  2. ###pg_stat_statements

  3. shared_preload_libraries = 'pg_stat_statements.so'

  4. pg_stat_statements.max = 10000

  5. pg_stat_statements.track = top

  6. pg_stat_statements.save = on

  7. pg_stat_statements.track_utility = on

  8. track_io_timing = on

  9. track_activity_query_size = 2048


  10. ###pg_profile

  11. track_activities = on

  12. track_counts = on

  13. track_io_timing = on

  14. track_wal_io_timing = on # Since Postgres 14

  15. track_functions = all

复制

2.3创建extension
//pg_profile/pg_sata_statements/db_link

  1. postgres=# CREATE EXTENSION dblink;

  2. postgres=# CREATE EXTENSION pg_stat_statements;

  3. postgres=# CREATE SCHEMA profile;

  4. postgres=# CREATE EXTENSION pg_profile SCHEMA profile;


  5. --查看extension

  6. postgres=# \dx

  7. List of installed extensions

  8. Name | Version | Schema | Description

  9. --------------------+---------+------------+--------------------------------------------------------------

  10. dblink | 1.2 | public | connect to other PostgreSQL databases from within a database

  11. pageinspect | 1.7 | public | inspect the contents of database pages at a low level

  12. pg_buffercache | 1.3 | public | examine the shared buffer cache

  13. pg_prewarm | 1.2 | public | prewarm relation data

  14. pg_profile | 4.2 | profile | PostgreSQL load profile repository and report builder

  15. pg_stat_statements | 1.7 | public | track execution statistics of all SQL statements executed

  16. plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language

  17. (7 rows)




  18. postgres=# \dx+ pg_profile

  19. Objects in extension "pg_profile"

  20. Object description

  21. -----------------------------------------------------------------------------------------------------------

  22. function profile.check_stmt_all_setting(integer,integer,integer)

  23. function profile.check_stmt_cnt(integer,integer,integer)

  24. function profile.cluster_stats(integer,integer,integer)

  25. function profile.cluster_stats_diff_htbl(jsonb,integer,integer,integer,integer,integer)

  26. function profile.cluster_stats_htbl(jsonb,integer,integer,integer)

  27. function profile.cluster_stats_reset(integer,integer,integer)

  28. function profile.cluster_stats_reset_diff_htbl(jsonb,integer,integer,integer,integer,integer)

  29. function profile.cluster_stats_reset_htbl(jsonb,integer,integer,integer)

  30. function profile.collect_obj_stats(jsonb,integer,integer,text,boolean)

  31. function profile.collect_pg_stat_statements_stats(jsonb,integer,integer,integer)

  32. function profile.collect_queries(oid,oid,bigint)

  33. function profile.create_baseline(character varying,integer,integer,integer)

  34. function profile.create_baseline(character varying,tstzrange,integer)

  35. function profile.create_baseline(name,character varying,integer,integer,integer)

  36. function profile.create_baseline(name,character varying,tstzrange,integer)

  37. function profile.create_server(name,text,boolean,integer,text)

  38. function profile.dbstats(integer,integer,integer,integer)

  39. function profile.dbstats_diff_htbl(jsonb,integer,integer,integer,integer,integer,integer)

  40. function profile.dbstats_htbl(jsonb,integer,integer,integer,integer)

  41. function profile.dbstats_reset(integer,integer,integer)

  42. function profile.dbstats_reset_diff_htbl(jsonb,integer,integer,integer,integer,integer)

  43. function profile.dbstats_reset_htbl(jsonb,integer,integer,integer)

  44. ……

  45. table profile.sample_settings

  46. table profile.sample_stat_archiver

  47. table profile.sample_stat_cluster

  48. table profile.sample_stat_database

  49. table profile.sample_stat_indexes

  50. table profile.sample_stat_indexes_total

  51. table profile.sample_stat_tables

  52. table profile.sample_stat_tables_total

  53. table profile.sample_stat_tablespaces

  54. table profile.sample_stat_user_func_total

  55. table profile.sample_stat_user_functions

  56. table profile.sample_stat_wal

  57. table profile.sample_statements

  58. table profile.sample_statements_total

  59. table profile.sample_timings

  60. table profile.samples

  61. table profile.servers

  62. table profile.stmt_list

  63. table profile.tables_list

  64. table profile.tablespaces_list

  65. view profile.v_sample_settings

  66. view profile.v_sample_stat_indexes

  67. view profile.v_sample_stat_tables

  68. view profile.v_sample_stat_tablespaces

  69. view profile.v_sample_stat_user_functions

  70. view profile.v_sample_timings

  71. (217 rows)

复制

3.创建快照

  1. postgres=# SELECT profile.snapshot() ;

  2. snapshot

  3. ------------------------

  4. (local,OK,00:00:00.64)

  5. (1 row)

复制

4.查询快照

  1. postgres=# select profile.show_samples();

  2. show_samples

  3. -----------------------------------

  4. (1,"2023-07-18 15:59:31-07",t,,,)

  5. (2,"2023-07-18 15:59:33-07",t,,,)

  6. (3,"2023-07-18 15:59:35-07",t,,,)

  7. (4,"2023-07-18 15:59:36-07",t,,,)

  8. (5,"2023-07-18 15:59:38-07",t,,,)

  9. (6,"2023-07-18 15:59:41-07",t,,,)

  10. (7,"2023-07-18 15:59:45-07",t,,,)

  11. (7 rows)


  12. postgres=# select * from profile.show_samples();

  13. sample | sample_time | sizes_collected | dbstats_reset | clustats_reset | archstats_reset

  14. --------+------------------------+-----------------+---------------+----------------+-----------------

  15. 1 | 2023-07-18 09:13:24-07 | t | | |

  16. 2 | 2023-07-18 09:13:26-07 | t | | |

  17. 3 | 2023-07-18 09:13:27-07 | t | | |

  18. 4 | 2023-07-18 09:13:28-07 | t | | |

  19. 5 | 2023-07-18 09:13:29-07 | t | | |

  20. 6 | 2023-07-18 09:13:29-07 | t | | |

  21. 7 | 2023-07-18 09:13:30-07 | t | | |

  22. 8 | 2023-07-18 09:14:13-07 | t | | |

  23. 9 | 2023-07-18 09:14:15-07 | t | | |

  24. (9 rows)

复制

5.awr报告
5.1awr报告生成
psql -qtc “select profile.get_report(1,7)” -o 1-7.html
1-7.html

5.2awr报告对比
psql -qtc “select profile.get_diffreport(1,2,3,4)” -o awr_report_postgres_16_17.html

6. 异常处理
获取快照报错:“could not establish connection”


//pg_profile—0.3.6.sql

1)源码找到138行

  1. ..

  2. CREATE FUNCTION take_sample(IN sserver_id integer, IN skip_sizes boolean

  3. ...

  4. -- Server connection

  5. PERFORM dblink_connect('server_connection',server_connstr); --FUNCTION take_sample -->line 138

复制

2)错误分析
调试dblink_connect方法无法连接数据库

3)查看配置pg_hba.conf
host all all 0.0.0.0/0 md5

4)修改认证方式trust
host all all 0.0.0.0/0 trust

5)问题解决

三、报告解析

分析报告从16:08开始,到16:32结束持续24分钟:

1. Server statistics

在采样时间24min内:
1)采样过程中增长了1089MB;
2)总共事务数6326008(4595161+1730846),平均每秒事务4393,事务回滚率为27%

1)ckpt_timeout 1500s
2)ckpt写时间耗费684秒
3)ckpt刷盘写数据2.69MB/s
4)平均归档日志生成量1.39MB/s

2. SQL query statistics

TOP SQL:
f3cbc714ba:执行1923 次,平均执行时长2145ms,最大执行时长6080ms;
cd47a0af8c执行1856次,平均执行时长2082ms,最大执行时长6656ms;

  1. //详细SQL语句

  2. SELECT A.fk_gson_coverbillno AS "gson_coverbillno",

  3. A.fmodifierid AS "modifier",

  4. A.fk_gson_bizday AS "gson_bizday",

  5. B.fk_gson_entrylimit AS "entry.gson_entrylimit",

  6. A.fk_gson_sourcesystem AS "gson_sourcesystem",

  7. A.fk_audit_status AS "audit_status",

  8. A.fk_gson_isfrombizsys AS "gson_isfrombizsys",

  9. A.fauditdate AS "auditdate",

  10. A.fsettlestatus AS "settlestatus",

  11. A.fk_gson_srcbilltypeid AS "gson_srcbilltype",

  12. A.fsettlementtypeid AS "settlementtype",

  13. A.frecorgid AS "recorg",

  14. B.ftaxrateid AS "entry.taxrateid",

  15. A.fbookdate AS "bookdate",

  16. A.fk_gson_absurdentry AS "gson_absurdentry",

  17. B.fk_gson_businessperiod AS "_f_332806439",

  18. A.fasstactid AS "asstact",

  19. A.fk_auditable_amounts AS "auditable_amounts",

  20. A.FId AS "id",

  21. B.FEntryId AS "entry.id",

  22. B.fk_auditedamount AS "entry.auditedamount",

  23. A.fbillstatus AS "billstatus",

  24. A.fisvoucher AS "isvoucher",

  25. B.fk_gson_supplierid AS "entry.gson_supplier",

  26. B.fk_gson_taxpayertype AS "_f_885504534",

  27. A.ftax AS "tax",

  28. B.fk_principal_amount AS "entry.principal_amount",

  29. A.fsalesorgid AS "salesorg",

  30. A.fk_gson_vouchernum AS "gson_vouchernum",

  31. B.fk_business_items AS "entry.business_items",

  32. B.fk_gson_recipients AS "entry.gson_recipients",

  33. A.fk_gson_isunvoucher AS "gson_isunvoucher",

  34. A.fbillno AS "billno",

  35. A.fk_business_period AS "gson_business_period",

  36. A.fisperiod AS "isperiod",

  37. A.fk_gson_auditperiod AS "gson_auditperiod",

  38. A.fmodifytime AS "modifytime",

  39. B.fexpenseitemid AS "entry.e_expenseitem",

  40. B.famount AS "entry.e_amount",

  41. A.fremark AS "remark",

  42. B.ftax AS "entry.e_tax",

  43. B.fk_gson_contractbillno AS "_f_1120494784",

  44. A.fbilltypeid AS "billtype",

  45. A.fk_gson_easnumber AS "gson_easnumber",

  46. B.frecamount AS "entry.e_recamount",

  47. A.fcurrencyid AS "currency",

  48. A.fk_gson_companyorgid AS "gson_companyorg",

  49. B.funsettleamt AS "entry.e_unsettleamt",

  50. A.fcreatetime AS "createtime",

  51. A.famount AS "amount",

  52. A.fcreatorid AS "creator",

  53. A.forgid AS "org",

  54. A.fk_gson_easvoucherstatus AS "gson_easvoucherstatus",

  55. A.fasstacttype AS "asstacttype",

  56. A.fauditorid AS "auditor",

  57. A.fbizdate AS "bizdate",

  58. A.funsettleamount AS "unsettleamount",

  59. A.fk_gson_bizbillno AS "gson_bizbillno",

  60. A.fk_audited_amount AS "audited_amount",

  61. A.frecamount AS "recamount",

  62. A.fsourcebillno AS "sourcebillno"

  63. FROM t_ar_finarbill$156 a

  64. LEFT OUTER JOIN t_ar_finarbillentry$156 b

  65. ON B.FId = A.FId

  66. WHERE (((A.fisvoucher = $1 AND (A.fbizdate >= $2)) AND (A.fbizdate < $3)) AND

  67. A.forgid = $4)

  68. ORDER BY A.fbizdate DESC LIMIT $5

复制

3.Schema object statistics

TOP表顺序读排序

TOP表block读取排序

TOP表DML排序

4.Vacuum-related statistics

5.Cluster settings during the report interval

6.TOP SQL分析及优化建议

结合SQL查询分析结果:
1) seq全表扫描
2) 基于AdoP(Parallel Hash),并行度2
3) Worker0/worker1 TOP排序内存95MB
4) a/b表读取大量buffers以及几十w rows
5) 基于字段fbizdate查询跨1年查询,fbizdate无索引
6) 表/索引膨胀
7) 统计信息缺失

优化思路:
1) 控制时间字段fbizdate查询跨度,1~3个月
2) 创建基于时间字段fbizedate索引
3) 增加work_mem大小(128MB->256MB)

4) 增加 shared_buffers大小 (1/4-1/2 OS mem)
5) random_page_cost设置为(4->1.1)
6) max_parallel_workers_per_gather(2->4)
7) max_parallel_maintenance_workers (2->4)
8) pg_repack/vacuum full analyze空间回收及统计信息收集更新



文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论