PostgreSQL の遅い SQL のトラブルシューティング

序文

いわゆる遅い SQL は、データベース内での実行時間が指定されたしきい値を超えるステートメントを指します。遅いクエリが多すぎると、ビジネスにとって非常に危険であり、何らかの理由でいつでも発生する可能性があります。私たちの経験によれば、データベースで最も一般的な問題は、データベースの速度を低下させる遅いクエリによって引き起こされます。インスタンス全体が「雪崩」を起こし、オンライン障害が発生します。この記事では、PostgreSQL の遅い SQL を見つけてトラブルシューティングする方法を紹介します。

1. ログパラメータの設定

slow_query_logMySQL は、低速ログ ストレージを設定するためのパラメータをユーザーに提供します。

# 是否开启慢日志
slow_query_log = 1

# 慢日志文件路径
slow_query_log_file = '/logs/slow.log'

# 慢日志阈值,取值范围 [0.000000-3600.000000]
long_query_time = 1

PostgreSQL は関連パラメータも提供します。

# -1 表示不记录语句
log_min_duration_statement = 100ms

# none, ddl, mod, all
# none: 表示不记录慢 SQL
# ddl: ddl 记录所有数据定义语句,例如 CREATE、ALTER 和 DROP 语句
# mod: DDL + INSERT, UPDATE、DELETE、TRUNCATE, 和 COPY FROM
# all: 所有语句都会被记录
log_statement = 'mod'
2023-09-14 14:07:46.695 CST [46385] LOG:  statement: update pgbench_accounts set bid = 11 where abalance = 101;
2023-09-14 14:07:53.698 CST [46385] LOG:  duration: 7003.518 ms

これにより、遅い SQL とエラー ログが 1 つのファイルにまとめられます。個人的には、特にコンテンツが多い場合に、見た目が良くないと思います。他の良い方法や経験がある場合は、コメント エリアに投稿してください。

2. pg_stat_statements プラグイン

pg_stat_statements モジュールは、実行統計サーバーによって実行されたすべての SQL ステートメントを追跡する手段を提供します。このモジュールはデフォルトでは有効になっていません。有効にする必要がある場合は、手動でコンパイルしてインストールし、構成ファイルを変更してデータベースを再起動し、使用前にモジュールを手動でロードする必要があります。

2.1 プラグインをインストールするかどうかの確認

プラグインをインストールする前に、PostgreSQL インストール ディレクトリでプラグインがコンパイルされているかどうかを確認する必要があります。

ll ./share/extension

出力:

总用量 52
-rw-r--r-- 1 root root 1246 914 15:38 pg_stat_statements--1.0--1.1.sql
-rw-r--r-- 1 root root 1336 914 15:38 pg_stat_statements--1.1--1.2.sql
-rw-r--r-- 1 root root 1454 914 15:38 pg_stat_statements--1.2--1.3.sql
-rw-r--r-- 1 root root  345 914 15:38 pg_stat_statements--1.3--1.4.sql
-rw-r--r-- 1 root root  305 914 15:38 pg_stat_statements--1.4--1.5.sql
-rw-r--r-- 1 root root 1427 914 15:38 pg_stat_statements--1.4.sql
-rw-r--r-- 1 root root  376 914 15:38 pg_stat_statements--1.5--1.6.sql
-rw-r--r-- 1 root root  806 914 15:38 pg_stat_statements--1.6--1.7.sql
-rw-r--r-- 1 root root  191 914 15:38 pg_stat_statements.control
-rw-r--r-- 1 root root  449 914 15:38 pg_stat_statements--unpackaged--1.0.sql
-rw-r--r-- 1 root root  310 95 10:21 plpgsql--1.0.sql
-rw-r--r-- 1 root root  179 95 10:21 plpgsql.control
-rw-r--r-- 1 root root  370 95 10:21 plpgsql--unpackaged--1.0.sql

pg_stat_statements ファイルに関する情報が表示され、プラグインがインストールされたことがわかります。関連するファイルが表示された場合は、プラグインがコンパイルされていないため、使用する前にコンパイルする必要があることを意味します。

2.2 プラグインのコンパイル

PostgreSQL ソース コード ディレクトリに移動し、次のコマンドを実行します。

# 进入插件目录
cd contrib/pg_stat_statements/

# 编译安装
make && make install

2.3 プラグインのロード

コンパイルとインストールが成功したことを確認したら、プラグインを使用できるようになります。まず、postgresql.conf構成ファイルを変更する必要があります。

# 加载动态库
shared_preload_libraries='pg_stat_statements'

# 记录语句的最大行数,默认 5000
pg_stat_statements.max = 10000

# 控制哪些语句会被该模块计数。指定 top 可以跟踪顶层语句(那些直接由客户端发出的语句)
# 指定 all 还可以跟踪嵌套的语句(例如在函数中调用的语句)指定 none 可以禁用语句统计信息收集。
pg_stat_statements.track = all

# 控制模块 是否 跟踪除了 “增删改查” 之外的命令,默认为 on
pg_stat_statements.track_utility = on

# 指定是否在服务器关闭之后还保存语句统计信息,默认为 on 关机前会持久化保存
pg_stat_statements.save = on

その後、重启数据库有効になります。

次に、psql を使用して PostgreSQL サービスに接続し、プラグインをロードします。

postgres=# create extension pg_stat_statements;     
CREATE EXTENSION

プラグインのステータスを確認します。

postgres=# SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements';     
        name        | default_version | installed_version |                          comment                          
--------------------+-----------------+-------------------+-----------------------------------------------------------
 pg_stat_statements | 1.7             | 1.7               | track execution statistics of all SQL statements executed

2.4 プラグインの使用

プラグイン ビューに直接クエリを実行して、TOP SQL の状況を確認します。

postgres=# select * from  pg_stat_statements limit 1;
-[ RECORD 1 ]-------+------------------------------------------------------------------------
userid              | 10                        //用户id
dbid                | 13547                     //数据库oid
queryid             | 1194713979                //查询id
query               | SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements'   //查询SQL
calls               | 1                         //调用次数
total_time          | 53.363875                 //SQL总共执行时间
min_time            | 53.363875                 //SQL最小执行时间
max_time            | 53.363875                 //SQL最大执行时间
mean_time           | 53.363875                 //SQL平均执行时间
stddev_time         | 0                         //SQL花费时间的表中偏差
rows                | 1                         //SQL返回或者影响的行数
shared_blks_hit     | 1                         //SQL在在shared_buffer中命中的块数
shared_blks_read    | 0                         //SQL从page cache或者磁盘中读取的块数
shared_blks_dirtied | 0                         //SQL语句弄脏的shared_buffer的块数
shared_blks_written | 0                         //SQL语句写入的块数
local_blks_hit      | 0                         //临时表中命中的块数
local_blks_read     | 0                         //临时表需要读的块数
local_blks_dirtied  | 0                         //临时表弄脏的块数
local_blks_written  | 0                         //临时表写入的块数
temp_blks_read      | 0                         //从临时文件读取的块数
temp_blks_written   | 0                         //从临时文件写入的数据块数
blk_read_time       | 0                         //从磁盘或者读取花费的时间
blk_write_time      | 0                         //从磁盘写入花费的时间

3. SQL が遅い場合のトラブルシューティング方法

3.1 現在のセッションをクエリする

SELECT pgsa.datname AS database_name
    , pgsa.usename AS user_name
    , pgsa.client_addr AS client_addr
    , pgsa.application_name AS application_name
    , pgsa.state AS state
	, pgsa.backend_start AS backend_start
	, pgsa.xact_start AS xact_start
	, extract(epoch FROM now() - pgsa.xact_start) AS xact_time, pgsa.query_start AS query_start
	, extract(epoch FROM now() - pgsa.query_start) AS query_time
	, pgsa.query AS query_sql
FROM pg_stat_activity pgsa
WHERE pgsa.state != 'idle'
	AND pgsa.state != 'idle in transaction'
	AND pgsa.state != 'idle in transaction (aborted)'
ORDER BY query_time DESC
LIMIT 5;

3.2 TOP SQLの表示

pg_stat_statements プラグインを再起動してリセットし、プラグインが現在のデータを再収集できるようにします。

create extension pg_stat_statements;
select pg_stat_reset();
select pg_stat_statements_reset();

トップ SQL を表示:

-- 总查询时间 TOP
select * from pg_stat_statements order by total_time desc limit 5;
-- 总 IO 消耗 TOP
select * from pg_stat_statements order by blk_read_time+blk_write_time desc limit 5;
-- 总调用次数 TOP
select * from pg_stat_statements order by calls desc limit 5;

異常なセッションが見つかった場合、通常はまずセッションを強制終了し、問題の原因を分析します。セッション強制終了の関連操作については、 「PostgreSQL セッション管理」を参照してください。

おすすめ

転載: blog.csdn.net/qq_42768234/article/details/132874343