:從PostgreSQL日志中快速定位慢查詢與性能瓶頸)
簡介pgBadger是一款用純Perl語言編寫的PostgreSQL日志分析器以解析速度見長能夠自動識別syslog、stderr、csvlog等常見日志格式并借助JavaScript圖表庫生成可視化報告適合DBA、運維工程師及需要深度排查數(shù)據(jù)庫性能的開發(fā)者在日常巡檢和故障分析中使用。資源為pgBadger 11.5的開源發(fā)行版共54個文件、約2.2MB除核心Perl腳本外還包含jQuery、jqplot等前端圖表資源、測試腳本、文檔與許可證說明整體結(jié)構(gòu)緊湊便于直接部署或二次開發(fā)。目前已有440人學(xué)習(xí)查看。壓縮包內(nèi)附有完整源碼、構(gòu)建配置如Makefile.PL與MANIFEST、單元測試樣例及詳細(xì)文檔讀者既可快速上手生成日志分析報表也能參考其內(nèi)部實現(xiàn)擴(kuò)展自定義功能同時自帶對gzip壓縮日志的支持有助于在日志量大、存儲受限的環(huán)境下高效完成分析任務(wù)。1. pgBadger 是什么一份 PostgreSQL 日志能榨出多少信息有一次線上慢查詢排查手里擺著 2GB 的 PostgreSQL 日志我 grep 了大半個下午才湊出幾條 5 秒以上的語句那滋味不想再試第二次。pgBadger 就是一個為提高速度而構(gòu)建的 PostgreSQL 日志分析器Perl 寫的命令行工具喂給它 PostgreSQL 的文本日志它吐出一份可交互的 HTML 報告慢查詢 Top、鎖等待、Checkpoint、臨時文件、全表掃描在這些區(qū)塊里一次看全。它不裝數(shù)據(jù)庫插件、不寫回數(shù)據(jù)庫、不需要改業(yè)務(wù)代碼唯一的前提是你把 PostgreSQL 的日志開關(guān)按格式打開。適合經(jīng)常要處理慢查詢的 DBA、后端負(fù)責(zé)人和 SRE日志越亂越有價值這份工具就是把“出了什么問題”從黑匣子里翻出來的那雙手。它是開源項目系統(tǒng)包里一條命令就能裝后面我會把配置、命令和踩過的坑一起展開。2. 先搞清它分析什么pgBadger 的輸入、報告與提速原理2.1 它吃的是原生日志不是 pg_stat_statements上手 pgBadger 之前必須先分清兩個概念。pg_stat_statements 是 PostgreSQL 內(nèi)置插件長期累計每類 SQL 的總耗時、執(zhí)行次數(shù)適合看趨勢而 pgBadger 解析的是數(shù)據(jù)庫進(jìn)程寫出來的原始日志文件回答的是“這段時間里到底發(fā)生了什么”。常見誤解是我已經(jīng)開了 pg_stat_statements還需要日志分析器嗎需要。pg_stat_statements 只記錄執(zhí)行過的語句聚合不記錄鎖等待過程、checkpoint 行為、臨時文件寫入、連接斷開這類旁路信息而這些往往是數(shù)據(jù)庫抖動的大頭。還有一層容易忽視的區(qū)別MySQL 的慢日志有固定表結(jié)構(gòu)、自帶查詢接口把這個習(xí)慣帶過來會發(fā)現(xiàn) PostgreSQL 完全不同——它的默認(rèn)日志是純文本沒有內(nèi)置慢日志表最多靠 log_line_prefix 控制格式。這就是 pgBadger 這類開源項目存在的意義把一條條裸日志變成可讀的指標(biāo)。能讓 pgBadger 出內(nèi)容的日志開關(guān)大致有五個我一般這樣開log_min_duration_statement 記錄超過閾值的慢語句log_checkpoints 記錄檢查點事件log_lock_waits 記錄鎖等待log_temp_files 記錄臨時文件log_autovacuum_min_duration 記錄自動 vacuum。每開一個報告里就多一個區(qū)塊開少了報告就瘦開多了文件漲得快第 3 章會給出完整配置。2.2 原生日志里有什么一行日志能被拆出哪些字段pgBadger 的解析邏輯本質(zhì)上就是把你日志里每個字段映射到報告維度。拿一條真實的日志為例2024-06-01 10:00:00.123 CST [23456]: [123-1] userdba,dbapp,apppsql,client127.0.0.1 LOG: duration: 2500.123 ms statement: SELECT * FROM orders WHERE user_id 123;拆開看這一行值多少錢開頭時間戳給報告時間軸[23456] 是進(jìn)程號用于區(qū)分連接[123-1] 是會話行號pgBadger 靠它把一條跨行消息拼回同一事件user、db、app、client 分別是用戶、數(shù)據(jù)庫、客戶端應(yīng)用、來源地址報告按庫按用戶分組全得靠它們duration 是慢查詢耗時statement 是語句正文。pgBadger 還會把這條語句里的數(shù)字參數(shù)替換成 ?做參數(shù)歸一化所以同一條 SQL 的不同參數(shù)值會聚合在一起排名不會因為 where 條件里數(shù)字不同就被拆成幾百行。這里面最容易被忽略的是 [123-1] 的會話行號。PostgreSQL 的日志里一條 ERROR 常常帶出 detail 和 context 多行內(nèi)容而只有第一行才有前綴里的完整字段沒有序號多行消息會被當(dāng)成獨立事件報告里的語句會被攔腰截斷。所以 log_line_prefix 里有沒有 %l直接決定報告能不能拼全語句。這也是為什么很多人換了 log_line_prefix 之后報告突然“少了一半數(shù)據(jù)”的根本原因。2.3 單遍流式解析快在哪和自寫腳本的差距標(biāo)題里“為提高速度而構(gòu)建”不是宣傳話術(shù)是它的實現(xiàn)方式?jīng)Q定的。pgBadger 處理日志是單遍流式一行一行讀正則提取出時間、進(jìn)程號、數(shù)據(jù)庫、用戶、語句耗時在內(nèi)存里做累加全程不把日志導(dǎo)入數(shù)據(jù)庫也不需要二次 ETL。這樣做最大的收益是內(nèi)存可控處理 10GB 級別的日志時內(nèi)存占用通常維持在幾百 MB 以內(nèi)而不是像導(dǎo)入數(shù)據(jù)庫統(tǒng)計那樣先把數(shù)據(jù)搬一遍。對比一下常見的替代方案就能看出差別。用 grep 加 awk 自己統(tǒng)計grep 本身很快但你要自己處理多行消息、自己按分鐘聚合、自己做 Top 排序?qū)懗鰜砟苡镁S護(hù)成本不小把日志灌進(jìn) PostgreSQL 再 SQL 分析要先清洗格式再建表導(dǎo)入日志一多大半時間花在導(dǎo)入而不是分析上。pgBadger 把這幾步都省了一條命令出 HTML還能直接讀 .gz、.bz2、.xz 壓縮日志不用先解壓占磁盤。新版本還支持多線程并行解析不同日志文件適合日志被按天切成很多小文件的場景。有一點要提醒它快不代表它對日志格式不挑。輸入格式越規(guī)整解析越快如果 log_line_prefix 配得亂七八糟它會先花時間做格式猜測甚至直接拒絕。所以想享受速度紅利前提是第 3 章的配置一步都不能省。2.4 開源分發(fā)與版本差異從 GitHub 拿源碼還是走系統(tǒng)包pgBadger 是開源項目用的 PostgreSQL License屬于寬松類許可證改完再分發(fā)也沒有像 GPL 那樣強(qiáng)的傳染性公司內(nèi)部二次開發(fā)負(fù)擔(dān)小。你直接搜 GitHub 的 darold/pgbadger 就能看到倉庫和 release 包很多 postgresql 安裝教程的末尾也會順手提它一句。獲取方式取決于你的操作系統(tǒng)。Debian/Ubuntu 的 apt 倉庫、RHEL/CentOS 的 EPEL 倉庫里基本都有 pgbadger 包一條命令裝完好處是依賴有人管。但系統(tǒng)倉庫里的版本可能落后 GitHub 一個大版本而新版本往往意味著支持更新的 PostgreSQL 日志格式比如 PostgreSQL 15 之后新增的 jsonlog 日志格式老版本 pgBadger 就不認(rèn)。我的習(xí)慣是生產(chǎn)環(huán)境優(yōu)先用系統(tǒng)包遇到“日志格式識別不了”這類問題時再去 GitHub 拉新 release 裝源碼版。裝完先跑一句 pgbadger --version確認(rèn)版本再往下走。3. 從 PostgreSQL 開日志到跑出第一份 HTML完整配置與命令3.1 PostgreSQL 日志參數(shù)log_line_prefix 必須按這個格式配pgBadger 解析依賴兩個東西日志里有內(nèi)容格式它能認(rèn)。PostgreSQL 側(cè)需要改 postgresql.conf 里的這幾項改完執(zhí)行 SELECT pg_reload_conf(); 即可不用重啟實例logging_collector on log_destination stderr log_line_prefix %t [%p]: [%l-1] user%u,db%d,app%a,client%h log_min_duration_statement 1000 log_checkpoints on log_lock_waits on log_temp_files 0 log_autovacuum_min_duration 0log_line_prefix 是 pgBadger 最看重的格式。%t 是帶毫秒的時間戳%p 是進(jìn)程號%l 是會話行號前面說過它負(fù)責(zé)把跨行日志拼回同一事件%u、%d、%a、%h 分別是用戶、數(shù)據(jù)庫、應(yīng)用名、客戶端地址報告里按庫按用戶分組就靠它們。注意行尾我留了一個空格這是為了讓消息正文與前綴隔開pgBadger 匹配前綴時會少很多邊界問題。log_min_duration_statement 設(shè) 1000 表示只記錄執(zhí)行超過 1 秒的語句如果你懷疑慢查詢被漏了先往小調(diào)比如 100代價是日志文件明顯變大。log_temp_files 設(shè) 0 表示記錄所有落盤的臨時文件不設(shè)這個值報告里的 Temp files 區(qū)塊就是空的。改完在 psql 里驗證SHOW log_line_prefix; SELECT pg_reload_conf();SHOW 輸出的字符串要和配置文件完全一致如果這里帶轉(zhuǎn)義字符或者換行pgBadger 那邊大概率要踩坑。注意 reload 只對新產(chǎn)生的日志生效已經(jīng)寫出去的舊日志格式不會變所以改完配置最好等幾分鐘再跑分析或者直接把舊日志移走。我在 5.1 里講的那個翻車案例就是沒等新日志直接排了 cron。3.2 安裝 pgBadgerapt、yum、源碼三選一安裝這一步?jīng)]有難度三個常見渠道如下# Debian / Ubuntu sudo apt install pgbadger -y # RHEL / CentOS 需要先開 EPEL sudo dnf install epel-release -y sudo dnf install pgbadger -y # 從 GitHub release 拿源碼包安裝 tar xzf pgbadger-*.tar.gz cd pgbadger-* perl Makefile.PL make sudo make installapt 和 dnf 適合圖省事的場景裝完直接有 pgbadger 命令。源碼安裝的好處是版本新perl Makefile.PL 階段會提示缺哪些 Perl 模塊常見的有 Text::CSV_XS 這類純文本解析加速模塊缺什么用 cpan 裝上即可。裝完驗證一下pgbadger --version命令能輸出版本就說明可執(zhí)行文件在 PATH 里。如果日志文件是 postgres 用戶寫的而你用 root 跑 pgbadger記得文件要能讀、目錄要有執(zhí)行權(quán)限否則后面會遇到 Permission denied。還可以順手看一眼 pgbadger --help 里的支持列表確認(rèn)你本地的版本支持哪些日志格式尤其是 jsonlog。3.3 第一條命令與報告驗證最小命令就一行指定輸出文件再把日志文件或通配符丟進(jìn)去pgbadger -o /tmp/pg_report.html /var/log/postgresql/postgresql-*.log-o 指定 HTML 輸出路徑。stderr 是最常見的日志格式pgBadger 會自動識別所以不用顯式寫 -f stderr如果你用的是 csvlog 或 jsonlog才需要在 -f 參數(shù)里指定。日志多、內(nèi)存少時可以加 -q 關(guān)閉進(jìn)度條輸出。跑完屏幕上會出現(xiàn)一行類似 “Html report written to /tmp/pg_report.html” 的提示然后用瀏覽器打開該文件。這里有個新手常踩的點日志文件名帶不帶日期后綴取決于你部署 PostgreSQL 時是否開了日志輪轉(zhuǎn)通配符寫得不對就會“找不到文件”。先 ls /var/log/postgresql/ 看真實文件名再寫命令比盲猜靠譜。如果命令報 “Wrong log_line_prefix” 或者解析完報告里全是 0回到 3.1 檢查 SHOW log_line_prefix 的輸出。第一次打開報告先看總請求量有沒有數(shù)字再翻到 Top Queries 看有沒有語句這兩處都有內(nèi)容才說明日志喂對了。3.4 新報告先看哪五個區(qū)塊第一次打開 HTML 報告很多人會被滿屏圖表晃到我建議只看五個區(qū)塊它們信息密度最高報告區(qū)塊能看出什么對應(yīng)日志開關(guān)General Statistics總請求數(shù)、每分鐘請求數(shù)、平均耗時先看量級是否異常log_min_duration_statementTop Queries慢語句排行按總耗時、平均耗時、最大耗時排序log_min_duration_statementCheckpoints檢查點頻率和耗時看是否寫盤壓力大log_checkpointsLock Waits鎖等待次數(shù)、等待時間定位鎖競爭log_lock_waitsTemp Files每次查詢落盤的臨時文件大小判斷 work_mem 夠不夠log_temp_filesTop Queries 里的語句是做了參數(shù)歸一化的同一條 SQL 不同參數(shù)值會被聚合成一類字面量被替換成 ?所以排名更公平不會出現(xiàn)同一邏輯的 SQL 因為參數(shù)不同被拆成幾百行。看的時候先按“總耗時”排再按“平均耗時”排前者找總量兇手后者找單次異常。另外報告里有按數(shù)據(jù)庫、按用戶的篩選器排查某個業(yè)務(wù)模塊的問題時先把范圍縮到一個庫再看 Top比全局列表直觀得多。4. 把 pgBadger 變成日常巡檢時間窗、增量解析與定時任務(wù)4.1 常用參數(shù)怎么設(shè)-b、-e、-t、-d 的組合用法單次跑報告只是開始要把 pgBadger 用成日常巡檢工具必須學(xué)會限定時間窗。下面幾個參數(shù)是我每次寫腳本都要用到的參數(shù)作用我的常用值-b / --begin只解析該時間之后的行“2024-06-01 00:00:00”-e / --end只解析該時間之前的行“2024-06-02 00:00:00”-t / --topTop 查詢顯示條數(shù)30-d / --dbname只看某個數(shù)據(jù)庫業(yè)務(wù)庫名-s / --size最多讀取多少日志量視日志大小而定組合起來是這樣pgbadger -b 2024-06-01 00:00:00 -e 2024-06-02 00:00:00 \ -t 30 -o /tmp/report_day.html /var/log/postgresql/postgresql-*.log-b 和 -e 解析的是日志里的時間戳不是文件修改時間所以即使日志文件混著好幾天的內(nèi)容也能精確切出一天。時間格式要帶空格命令行里必須加引號這個細(xì)節(jié)在 cron 里最容易翻車少一對引號 shell 就把時間拆成了兩個參數(shù)。如果你只要最近一小時-b 也可以用 date 命令動態(tài)生成但注意時區(qū)和第 5 章那個坑。-s我一般用在探測場景不確定日志有多大、機(jī)器內(nèi)存緊的時候先限制只讀最后 2GB 跑一份小報告觀察資源消耗再決定要不要全量。4.2 增量分析不要讓報告一次比一次慢全量日志只有幾 GB 時多久跑一次無所謂跑了一個月后還每次從頭解析就是在浪費時間。增量分析的目的很直接只處理上次跑完之后新產(chǎn)生的日志。常見做法有兩種。第一種是時間窗法配合日志輪轉(zhuǎn)每天用 -b 限定昨天零點、-e 限定今天零點只解析前一天。第二種是偏移記錄法pgBadger 支持記錄上次解析到的日志偏移下次從偏移處繼續(xù)參數(shù)名在不同版本里略有差別裝好后先跑一下 pgbadger --help 確認(rèn)你本地版本的寫法。我自己的生產(chǎn)環(huán)境更常用時間窗法因為邏輯直白、排障容易偏移法省解析時間但日志被輪轉(zhuǎn)刪除后會丟失中間段反而不適合日志保留期短的環(huán)境。# 每天只解析 24 小時內(nèi)的日志 pgbadger -b $(date -d yesterday 00:00 %Y-%m-%d %H:%M:%S) \ -e $(date %Y-%m-%d %H:%M:%S) \ -o /var/www/pgbadger/daily.html \ /var/log/postgresql/postgresql-*.log這段腳本用 date 動態(tài)生成起止時間配合 crontab 每天執(zhí)行就是一套最樸素的增量日報。注意 date -d 語法在 Linux 和 macOS 上不一樣Linux 用 -dmacOS 要寫 -v-1d服務(wù)器場景基本都是 Linux不會有歧義。切換增量方式或者日志目錄變化之后先跑一次全量報告作為新基線免得新舊報告口徑對不上。4.3 用 cron 定時生成日報并自動清理舊報告定時任務(wù)我放在 /opt/scripts/pgbadger_daily.sh內(nèi)容比單條命令多兩件事輸出目錄按日期命名、超過 90 天的舊報告自動刪除。日志權(quán)限記得給執(zhí)行用戶可讀權(quán)限我是用一個專門的 postgres 系統(tǒng)賬戶跑的避免和業(yè)務(wù)權(quán)限攪在一起。#!/bin/bash LOG_DIR/var/log/postgresql OUT_DIR/var/www/pgbadger YESTERDAY$(date -d yesterday %Y-%m-%d) TODAY$(date %Y-%m-%d) pgbadger -b $YESTERDAY 00:00:00 -e $TODAY 00:00:00 \ -o $OUT_DIR/report-$YESTERDAY.html \ $LOG_DIR/postgresql-*.log /dev/null find $OUT_DIR -name report-*.html -mtime 90 -deletecrontab 里加一行30 2 * * * /opt/scripts/pgbadger_daily.sh /var/log/pgbadger_cron.log 21每天凌晨 2 點半執(zhí)行正好避開業(yè)務(wù)高峰早上上班打開瀏覽器就能看到昨天全天的報告。重定向到日志文件是為了排障腳本里 date、通配符出錯時能看到痕跡。跑失敗了別只盯著 pgbadger 報錯先看這個日志文件血淚經(jīng)驗是八成問題出在引號或文件權(quán)限而不是 pgBadger 本身。4.4 巡檢閾值哪些數(shù)字一報警就該處理報告生成只是第一步會讀才有效果。我按踩過坑的經(jīng)驗給一檔初始閾值你可以根據(jù)業(yè)務(wù)調(diào)整指標(biāo)注意閾值說明每分鐘請求數(shù)較前一日驟降 50% 以上連接可能被鎖或連接池耗盡慢查詢最大耗時超過 5 秒單語句異常重點看 Top Queries鎖等待次數(shù)大于 0 且平均等待超 1 秒業(yè)務(wù)側(cè)要查鎖來源臨時文件總量單日累計超 1GB優(yōu)先調(diào)大 work_mem 再觀察Checkpoint 間隔頻繁且耗時高檢查 max_wal_size 和磁盤寫入這些閾值不是真理是一份讓你有據(jù)可依的起點。每種業(yè)務(wù)對耗時的容忍度不同運行一個月后把報告里的數(shù)字和線上故障時間對上再回改閾值比拍腦袋準(zhǔn)得多。特別是臨時文件這個指標(biāo)它和你業(yè)務(wù)里報表查詢的頻度強(qiáng)相關(guān)同一套閾值放到 OLTP 和 OLAP 集群上完全是兩個世界。5. 避坑pgBadger 出真報告前最容易翻車的五個地方5.1 log_line_prefix 不匹配一上來就報錯現(xiàn)象命令執(zhí)行后立刻報 “Wrong log_line_prefix” 或 “cant parse”報告文件沒生成。原因postgresql.conf 里的 log_line_prefix 不是 pgBadger 認(rèn)識的格式常見是少了 %t 或 %l或者手寫的格式和實際配置有出入。解決先在 psql 里執(zhí)行 SHOW log_line_prefix;拿真實輸出檢查。最簡單的做法是把 3.1 的配置原樣粘貼并 reload再等新日志產(chǎn)生后重跑。如果你的前綴必須帶業(yè)務(wù)標(biāo)識把 SHOW 輸出的字符串原樣用 -p 參數(shù)傳給 pgBadger兩邊對齊就不再報錯。這屬于格式對不上就老老實實改配置的問題沒有玄學(xué)空間。5.2 報告空白但日志明明有內(nèi)容現(xiàn)象報告生成成功打開 General 頁面也有連接數(shù)但 Top Queries 和慢查詢區(qū)塊是空的。原因日志里只有連接、斷開的記錄沒有語句執(zhí)行時長。log_min_duration_statement 沒開或者設(shè)得太大示例里設(shè) 1000 意味著只有超過 1 秒的語句才帶 duration 字段小于 1 秒的語句完全不進(jìn)日志。解決SHOW log_min_duration_statement; 確認(rèn)值。想分析所有語句臨時設(shè)成 0日志量和報告體積會明顯變大不要一直開著想找相對慢的設(shè) 100 到 300 更實用。另外注意 log_statement 和 log_min_duration_statement 不要同時開兩者疊加會產(chǎn)生重復(fù)記錄報告里的數(shù)字是虛胖的。5.3 報告時間和本地時間對不上現(xiàn)象報告的橫軸是 UTC 時間和業(yè)務(wù)日志、告警平臺差 8 小時對不上號。原因PostgreSQL 的 log_timezone 參數(shù)控制日志時間戳?xí)r區(qū)默認(rèn)可能跟服務(wù)器本地時區(qū)不一致pgBadger 按日志內(nèi)的 %t 解析不換算所以報告時間和日志本身一致但和你 date 看到的本地時間不一致。解決在 postgresql.conf 里把 log_timezone 設(shè)成業(yè)務(wù)所在時區(qū)比如log_timezone Asia/Shanghaireload 后重新生成的日志就對齊了。歷史日志沒法補(bǔ)救只能按差值換算。寫 -b/-e 時也帶上時區(qū)偏移比如 “2024-06-01 00:00:0008”讓 pgBadger 明確邊界避免整點對不上。5.4 增量數(shù)字重復(fù)越堆越大現(xiàn)象每天的日報里某個慢查詢的總耗時比昨天翻倍明明線上沒有新慢查詢。原因時間窗沒生效cron 命令里的引號丟了date 命令實際執(zhí)行成了兩個參數(shù)-b 被 shell 拆掉pgBadger 退化成解析全部日志或者日志文件沒輪轉(zhuǎn)天天解析同一批文件。解決先手動跑一遍 4.3 的腳本看生成報告的 General 頁時間范圍是不是只有昨天一天再把日志輪轉(zhuǎn)配好建議 PostgreSQL 側(cè)按天產(chǎn)生新文件已歸檔的壓縮移走。清理一次全量報告作為新基線之后增量才會準(zhǔn)。增量功能依賴穩(wěn)定的文件列表日志文件改個名、目錄換位置都會打破它變更后先跑一次全量。5.5 日志太大把磁盤和內(nèi)存打爆現(xiàn)象解析 30GB 日志時/tmp 寫滿或內(nèi)存飆升機(jī)器卡死。原因pgBadger 雖然流式讀日志但最后生成 HTML 需要把所有聚合結(jié)果寫進(jìn)一個文件報告本身可能幾百 MB開啟多線程并行解析時每個線程都有自己的緩沖內(nèi)存占用成倍上漲輸出路徑默認(rèn)在 /tmp小分區(qū)很快被撐爆。解決先用 -s 限制日志讀取量探測性能比如 pgbadger -s 2G -o /tmp/test.html 先跑一小段把 -O 指向有足夠空間的目錄別用 /tmp日志按天拆開、分批解析成多個報告再配合歸檔。壓縮日志能減少 I/OpgBadger 直接支持 .gz 文件建議輪轉(zhuǎn)時順手 gzip既省磁盤又省命令行通配符的長度。6. 接進(jìn)告警與抽查驗證用 pg_stat_statements 給報告背書pgBadger 報告的價值在于快速定位但別把唯一一份報告當(dāng)真相。我現(xiàn)在的習(xí)慣是報告出了 Top 慢查詢先去數(shù)據(jù)庫里用 pg_stat_statements 交叉驗證一遍。SELECT query, calls, total_exec_time, mean_exec_time FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 5;注意 PostgreSQL 11 之前的字段叫 total_time之后改成了 total_exec_time版本不同查詢也要跟著改。對照方式很簡單報告里的 Top 語句應(yīng)該能在上面結(jié)果里找到同款數(shù)值量級大致一致。如果報告里某條語句總耗時很高、pg_stat_statements 里卻幾乎沒有先別急著下結(jié)論檢查是不是日志采樣窗口和統(tǒng)計窗口不一致或者語句在日志里被拆成了多行沒拼全。報告負(fù)責(zé)“懷疑”pg_stat_statements 負(fù)責(zé)“確認(rèn)”兩個工具對著看就不會被單個視角帶偏。關(guān)于歸檔我還會把每天的 HTML 報告按周打包保留 90 天方便追溯“上周五那次抖動是不是同一批慢查詢”。打包用 tar 就行不展開。真要接告警我會在 cron 腳本里加一行 grep從當(dāng)天日志里撈出耗時最大的那條語句拼成一行文本告警不要直接解析 HTML那東西改版一次壞一次。最后分享一個血淚教訓(xùn)我剛開始用 pgBadger 時改完配置直接排了 cron結(jié)果第二天報告全空查了一圈發(fā)現(xiàn)是 reload 之后忘記等新日志產(chǎn)生歷史日志又是舊前綴白白浪費一天?,F(xiàn)在我的固定動作是改完配置先手動跑一條 10 分鐘的小日志確認(rèn)報告有數(shù)據(jù)、時間正確再上 cron。先小后大、先時間窗后全量、先單文件后通配符這三條順序能擋住絕大部分翻車。希望幫到你。本文還有配套的精品資源點擊獲取