Aurora Postgresパフォーマンス

インスタンスの作成

パフォーマンス関連の設定値

  • クラスタ構成オプション: Aurora I/O-Optimized
  • r6i.large(ARMプロセッサ, 2vCPU, 16GBメモリ, NW帯域5Gbps弱(4500とか))
    • 選べるのは、メモリ最適化クラスorバースト最適化クラス
  • RDS Proxy利用しない
  • 暗号を有効化: ON(パフォーマンスに影響あるか不明)

パフォーマンスモニタリング関連

  • Performance Insights: ON
  • DevOps Guru: ON
    • 「DB インスタンスのパフォーマンスの異常を自動的に検出し、レコメンデーションを提供します。」
  • 拡張モニタリング: ON
    • 詳細度: 1秒(デフォルト60秒)

  • Aurora(Postgres)15.3(2023.7.13時点最新)
  • マルチAZ配置: Auroraレプリカを作成しない
  • EC2コンピューティングリソースに接続: ON, 既存のEC2インスタンスを選択
  • ログのエクスポート: PostgreSQLログ: ON
    • 「CloudWatch Logs に発行するログタイプを選択します」

テーブル作成

T1テーブルを作成

set search_path to "PFS";

create table t1( c1 integer ) ;

1億件投入

参考サイト

INSERT INTO t1( c1 ) SELECT i FROM generate_series(1, 100000000) as i ;

5分弱で返ってきた

INSERT 0 100000000

Query returned successfully in 4 min 51 secs.

パフォーマンスモニタリング系の見え方

Performance Insights

ディメンションタブ

CPU: 35%
IO:AuroraStorageLogAllocate: 22%

合計すると57%

CPU35%ってのは、これ待機イベントだから、CPU待ちのことかな..? IO待ちが表示されてないけど、IO待ちないとかありえないよね..? CPU待ちがあるならIO待ちがあるよね?? ない?? 遅延書き込みとか??

詳細が良く分からない..

メトリクス – 新規 タブ

画面左上~中央

画面右上~中央

画面下側

  • メトリクス一覧

CPU 使用率 (%)
空きメモリ (バイト)
FreeableMemoryIO レイテンシー (ミリ秒)
IO オペレーション (/秒)
IO スループット (バイト/秒)
IO ディスクキューの深さ (リクエスト)
バキューム: 使用されている最大のトランザクション ID(トランザクション)
トランザクションの最大アイドル時間 (秒)
ネットワークスループット (バイト/秒)
接続の使用率 (接続)
セッション (セッション)
クエリ (/秒)
タプル: DML(タプル/秒)
タプル: DML(タプル/秒)
トランザクション (1 秒あたりのトランザクション)
進行中のトランザクション (1 秒あたりのトランザクション)
IO キャッシュとディスク読み取り (ブロック/秒)
デッドロック (デッドロック/分)

日本語表記なのと、後述の、クラスタ/ライターインスタンスのメトリクス数と比べるとかなり絞られてる感じ。必要そうなものは人とおりある感じはするけど。


クラスター/ライターインスタンスを選択して詳細画面で、モニタリングタブ見る

クラスター/ライターインスタンスでそれぞれメトリクス違うな..

  • クラスタ

AuroraEstimatedSharedMemoryBytes
BackupRetentionPeriodStorageUsed
BufferCacheHitRatio
CommitLatency
CommitThroughput
CPUUtilization
Deadlocks
DiskQueueDepth
EBSByteBalance%
EBSIOBalance%
EngineUptime
FreeableMemory
FreeLocalStorage
MaximumUsedTransactionIDs
NetworkReceiveThroughput
NetworkThroughput
NetworkTransmitThroughput
OldestReplicationSlotLag
RDSToAuroraPostgreSQLReplicaLag
ReadIOPS
ReadLatency
ReadThroughput
ReplicationSlotDiskUsage
StorageNetworkReceiveThroughput
StorageNetworkThroughput
StorageNetworkTransmitThroughput
SwapUsage
TotalBackupStorageBilled
TransactionLogsDiskUsage
VolumeBytesUsed
VolumeReadIOPs
VolumeWriteIOPs
WriteIOPS
WriteLatency
WriteThroughput

  • ライターインスタンス

AuroraEstimatedSharedMemoryBytes
BufferCacheHitRatio
CommitLatency
CommitThroughput
CPUUtilization
DatabaseConnections
DBLoad
DBLoadCPU
DBLoadNonCPU
Deadlocks
DiskQueueDepth
EBSByteBalance%
EBSIOBalance%
EngineUptime
FreeableMemory
FreeLocalStorage
MaximumUsedTransactionIDs
NetworkReceiveThroughput
NetworkThroughput
NetworkTransmitThroughput
OldestReplicationSlotLag
RDSToAuroraPostgreSQLReplicaLag
ReadIOPS
ReadLatency
ReadThroughput
ReplicationSlotDiskUsage
StorageNetworkReceiveThroughput
StorageNetworkThroughput
StorageNetworkTransmitThroughput
SwapUsage
TransactionLogsDiskUsage
WriteIOPS
WriteLatency
WriteThroughput

diffってみる

左がクラスタ、右がライターインスタンス

ウィンドウの横幅が足りないと縦に文字が重複したような表示になるので、画像+アコーディオン(テキストで見たい人向け)で貼ります

/tmp \ diff -y cluster instance
#cluster                                                      | #instance
AuroraEstimatedSharedMemoryBytes                                AuroraEstimatedSharedMemoryBytes
BackupRetentionPeriodStorageUsed                              <
BufferCacheHitRatio                                             BufferCacheHitRatio
CommitLatency                                                   CommitLatency
CommitThroughput                                                CommitThroughput
CPUUtilization                                                  CPUUtilization
                                                              > DatabaseConnections
                                                              > DBLoad
                                                              > DBLoadCPU
                                                              > DBLoadNonCPU
Deadlocks                                                       Deadlocks
DiskQueueDepth                                                  DiskQueueDepth
EBSByteBalance%                                                 EBSByteBalance%
EBSIOBalance%                                                   EBSIOBalance%
EngineUptime                                                    EngineUptime
FreeableMemory                                                  FreeableMemory
FreeLocalStorage                                                FreeLocalStorage
MaximumUsedTransactionIDs                                       MaximumUsedTransactionIDs
NetworkReceiveThroughput                                        NetworkReceiveThroughput
NetworkThroughput                                               NetworkThroughput
NetworkTransmitThroughput                                       NetworkTransmitThroughput
OldestReplicationSlotLag                                        OldestReplicationSlotLag
RDSToAuroraPostgreSQLReplicaLag                                 RDSToAuroraPostgreSQLReplicaLag
ReadIOPS                                                        ReadIOPS
ReadLatency                                                     ReadLatency
ReadThroughput                                                  ReadThroughput
ReplicationSlotDiskUsage                                        ReplicationSlotDiskUsage
StorageNetworkReceiveThroughput                                 StorageNetworkReceiveThroughput
StorageNetworkThroughput                                        StorageNetworkThroughput
StorageNetworkTransmitThroughput                                StorageNetworkTransmitThroughput
SwapUsage                                                       SwapUsage
TotalBackupStorageBilled                                      <
TransactionLogsDiskUsage                                        TransactionLogsDiskUsage
VolumeBytesUsed                                               <
VolumeReadIOPs                                                <
VolumeWriteIOPs                                               <
WriteIOPS                                                       WriteIOPS
WriteLatency                                                    WriteLatency
WriteThroughput                                                 WriteThroughput

DatabaseCOnnectionsとかDBLoad/DBLoadCPU/DBLoadNonCPUを見るときはライターインスタンスのメトリクスを見ると。ふむふむ。

あとCloudWatchでもそう思うときがあるんだけど気になるのが、メトリクスの間隔を丸めたとき(1分とか10分とか1時間とか)に、見える値って変わるんじゃ??ってこと。この機に見てみる。

上記は1秒おきのデータで見てるので、これを1時間に変えてみる。

Performance Insights(の、メトリクス – 新規タブ)には、間隔を変えるオプションはなかった。範囲を6分間で絞ってるけど、1分間ごとに棒グラフの棒が60個くらいあるように見えるので、1秒おきのデータ表示になってそう(DBの設定で詳細モニタリングの間隔を1秒にしてある影響かな??)。

クラスタ/ライターインスタンスのモニタリングタブを、1秒置きから広げてみる(テーブルのデータ投入時間が5分弱だったので1分~5分に伸ばすくらいが限界)

  • クラスタ

特にCPU使用率と、ディスクキューを見る

1秒間隔のCPU使用率: 80%でしばらく継続

1秒間隔のディスクキュー: max900くらい

1分間隔の場合

1分間隔のCPU使用率: 丸めこみ差異なし

1分間隔のディスクキュー: 丸めこみ差異なし

なぜか1分間隔にすると5:54時点のデータも見えたけど、丸めこみはなかった。

5分間隔にすると、たぶん範囲で6分間を指定してるせいで、データが取れない。もう少し前後の範囲を広げて、5分(CloudWatchのデフォ)とか1時間とかで見てみる

範囲の前後を5分広げる (5:54-6:00だったのを、5:49-6:05に変更)

5分間隔

CPU: 丸まってない

ディスクキュー: 4分の1くらいに丸まった

やっぱこうなるのか.. これは要注意。

範囲を前後30分に広げて1時間間隔のデータを見てみる

範囲を、元々5:54-6:00なので、切り良く5:30-6:30を設定

1時間間隔はなぜか全然表示されない(範囲を2時間とかにしてもなぜか表示されない)

15分間隔だと表示されるので15分間隔を見る

CPU: 1秒間隔のときより半分に丸め込み

ディスクキュー: 1秒間隔のときより10分の1に丸め込み

うーん、これだとかなり判断変わるよなあ..

ちなみに、時間の範囲指定、は全然影響なかった。負荷かけてる5分間でも、前後1時間とか間延びしてても、グラフの横幅の傾斜が変わるくらいで、値の丸め込みはなかった。

なので、start/endの範囲指定は負荷かけてる時間帯が含まれてるなら良くて、でもそのデータの間隔は1秒おきじゃないと正しいデータが取れない。

参考) 1時間範囲での1秒間隔データ

CPU

ディスクキュー

1秒->5分の間を刻んで見てみる

5秒(今回はキャプチャのしやすさの都合で間にDBLoadCPUが見えてます)

丸め込みなし

10秒: 丸め込みなし

30秒: 丸め込みなし

1分(画面表示は1 minute)

丸め込みなし

5分

CPU丸め込みなし、ディスクキュー 3分の1前後に丸め込み

15分

CPU半分、ディスクキュー10分の1に丸め込み

1時間(表示は1 hour)

データ取れず

1hour、直近3時間にしたら取れた。でも意味はないデータ

つまり、CloudWatch見るときのデータ間隔は、最低でも1分にしないとちゃんとデータ見れないよと。デフォ5分だとディスクキューが小さい値が表示されてるので、1分に変更してから見たり、データもらう必要があるよと。

ディスクだと、性能限界かとかベースライン/バースト性能のスペックと比較してどうかとか、数値で見るので、正しい値取れないと、ただしい対策取れなくなる。

CloudWatchのデータ間隔での丸め込みが分かってすっきりした

1億件のテーブルについて、データ確認

ここでデータといってるのはレコードの内容ではなく(レコードは上記で一括で登録したものなので)、占有してるサイズとかそういう情報です

pgAdminのstatistics

件数100000000(1億件)
Live tuples100003053
Heap blocks read131074
Heap blocks hit
102117915
Last autovacuum2023-07-13 05:59:40.024014+00
Last autoanalyze2023-07-13 05:59:40.95705+00
Table size3458 MB

全体は以下。データがない項目多し

1億件を、1カラム(平均バイト長は5くらいだろうか..)で投入すると、3458MB(大体3.37GB)になる。

そして、その作成には4分51秒かかる。

CloudWatch(クラスタ/ライターインスタンスのメトリクスタブ), Performance Insightsより、大体の待機時間は「CPU: 35%, IO:AuroraStorageLogAllocate: 22%」で、他の待機イベントと合わせてざっくり50%なので、残りの50%にIO待機が含まれてる感じか??(いや、IO待機が含まれてるならそう出るような。IO待機ないのか??でもデータ投入でIO待機なしでCPUフルに使えてるとかありえる??遅延書き込み??)

4分51秒 = 291s

3458MB / 291s = 約11.88MB/s

1億 / 291s =

秒間のレコード生成

レコード数: 343,642行
(正確: 343642.6116838488)

サイズ: 11MB/s

サイズでいうと11MB/sってちょっと少なく感じるけど、秒間34万件書き込めてると思うと早いか..

Aurora Postgresqlインスタンス作成時にEBSの選択なかったけど、ストレージタイプとIOPS/スループットってどのくらいなんだろ??

大量レコード投入時のIOPS見てみる

データ投入したの、7/13 14:54-15:00(UTC: 5:54-6:00)なのだが、今モニタリングタブ見ると、1秒間隔のデータが見れなくなっていた.. 1秒間隔のデータ見れる期限は短いのか??

5秒、10秒、30秒も表示されず、1分間隔は表示された。

1分間隔のデータは、丸め込みでの小さいものとなっていなかった(CPU約85%, ディスクキュー約900)ので、これを利用可と考える。

IOPSはPerformanceInsightsにはないので、クラスタのモニタリングタブを見る。(クラスタは、ライターインスタンスの方のメトリクスを大概含んでる※connectionsとかはライターインスタンス見る必要あり なので、クラスタのモニタリングタブ見る)

メトリクスの検索窓でReadと入力して読み込み系見る

検索窓でWriteを入力して書き込み系見る

これ見ると、データ投入後2分間に若干の読み込み(140IOPSくらい, ハードディスクだとそれなりのIOだけど.. 高性能のクラウドのSSDだと低く見える)が発生してる。書き込みと比べると無風くらいに感じる。

書き込みの方は、グラフで読み取りづらいけど360kのIOPSが継続してて、スループットは50MB/sで継続。360k = 36万IOPSかー!Auroraのディスク速いな!

ここ数年標準になってきたgp3のベースラインが3000とかで、それでも十分だし、自分の仕事の大規模環境でもgp3のIOPSを15000, スループット1GB(だったっけ??たぶんその辺)とかで使えるようにインスタンスタイプもX1の最新のやつとか選ぶ感じ。

そう考えるとAuroraの36万IOPSはかなりすごいな。

データ件数を大量登録しようとして、なんとなく、1000万件でも結構早く終わりそうだから、1億件か10億件か迷って、自分が思う世間の大規模環境(データが多い環境)でよくありそうな1億件を投入してみたけど、これが5分弱で終わるって相当な性能なんだな..

カラム数は1つで、投入データもintegerで数桁で、テーブルサイズは3.37GBと、そこまでおおごとに考えなかったけど、これ逆に多数のカラムで構成した同じサイズより、カラム1個でレコード数大量の方が、フェッチサイズ的なもの(トランザクション単位とかカーソル進行とか)で負荷かける感じになってるような気がする。

たしかに、過去に金融系のDBリプレイスしたとき、20億行あるテーブルのサイズって3.37GBとかじゃなかった気がする。DB全体で2TBとかあって、その中の巨大なコアなテーブル100GBレベルだったような。oracleで、統計取れないので統計取るときのパーセンテージで全体の10%?とか指定してたし、データファイル格納してるNetAppから新しいハードのNetAppへの移行(スナップショット的な機能を利用しての移行)も20時間くらいかかったような..

カラム数もっと商用/業務アプリ的に100個~とかにしてやってみると良さそうだよなあ。

翌日、DevOps Guruに機械学習かけたパフォーマンス情報見れると知って見てみたけど特に何もでてなかった

テーブル再作成、データ再投入(100万件)

1億件だと時間かかるので100万件にしてみる

テーブルdropして再作成


set search_path to "PFS";

create table t1( c1 integer ) ;

100万件投入

INSERT INTO t1 (c1) 
 SELECT 
     i
 FROM
     generate_series(1, 1000000) as i
;

3秒で完了

INSERT 0 1000000

Query returned successfully in 3 secs 379 msec.

単純にselectしてみる

初回実行(キャッシュなし?テーブル作成時にはキャッシュ作成されてないかな??)

3.263sで返却

select * from t1;

2回目(キャッシュあり?)

2.955s

3回目

3.195s

キャッシュ効いてこれ??キャッシュ効いてない??

PostgreSQLの実行計画とかキャッシュ状態見る方法はと..

そうだ、explainを先頭につけるだけだった

で、anayze/bufferとかもつけると、より詳細な情報やバッファ情報出してくれる

ここまでpgAdminでやってたけど、SQLの実行結果を記事にコピペしたいので、psqlのクライアントツールをEC2にインストールする

sudo yum search postgresql | grep -i client

yum install -y postgresql.aarch64

インストールされるRPM2個だけですごい軽くて良い

Total download size: 3.3 M
Installed size: 17 M
Downloading packages:
(1/2): postgresql-libs-9.2.24-8.amzn2.0.1.aarch64.rpm
(2/2): postgresql-9.2.24-8.amzn2.0.1.aarch64.rpm

接続したらエラーでた

# psql -h RDSエンドポイント -U ユーザー -d DB
psql: SCRAM authentication requires libpq version 10 or above

さっきインストールしたのに含まれるのはver9

# yum deplist postgresql.aarch64 | grep libpq -A1
  dependency: libpq.so.5()(64bit)
   provider: postgresql-libs.aarch64 9.2.24-8.amzn2.0.1

新しいクライアントverを入れてみようか..

参考サイト

【超速】AWS EC2インスタンスにpostgresql client 12をインストールする - Qiita
# yum remove postgresql.aarch64 -y

# rpm -qa | grep -i postg
postgresql-libs-9.2.24-8.amzn2.0.1.aarch64

# rpm -e postgresql-libs-9.2.24-8.amzn2.0.1.aarch64

pgdg-redhat… rpmをインストールして、yum updateしたらいっぱいエラーでた

# sudo yum update
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
pgdg-common/aarch64/signature                                         |  490 B  00:00:00
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG
Importing GPG key 0x442DF0F8:
 Userid     : "PostgreSQL RPM Building Project <pgsql-pkg-yum@postgresql.org>"
 Fingerprint: 68c9 e2b9 1a37 d136 fe74 d176 1f16 d2e1 442d f0f8
 Package    : pgdg-redhat-repo-42.0-32.noarch (installed)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG
Is this ok [y/N]: y
pgdg-common/aarch64/signature                                         | 2.9 kB  00:00:03 !!!

https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-7-aarch64/repodata/repomd.xml:
[Errno -1] repomd.xml signature could not be verified for pgdg-common Trying other mirror. One of the configured repositories failed (PostgreSQL common RPMs for RHEL / CentOS 7 - aarch64), and yum doesn't have enough cached data to continue. At this point the only safe thing yum can do is fail. There are a few ways to work "fix" this: 1. Contact the upstream for the repository and get them to fix the problem. 2. Reconfigure the baseurl/etc. for the repository, to point to a working upstream. This is most often useful if you are using a newer distribution release than is supported by the repository (and the packages for the previous distribution release still work). 3. Run the command with the repository temporarily disabled yum --disablerepo=pgdg-common ... 4. Disable the repository permanently, so yum won't use it by default. Yum will then just ignore the repository until you permanently enable it again or use --enablerepo for temporary usage: yum-config-manager --disable pgdg-common or subscription-manager repos --disable=pgdg-common 5. Configure the failing repository to be skipped, if it is unavailable. Note that yum will try to contact the repo. when it runs most commands, so will have to try and fail each time (and thus. yum will be be much slower). If it is a very temporary problem though, this is often a nice compromise: yum-config-manager --save --setopt=pgdg-common.skip_if_unavailable=true failure: repodata/repomd.xml from pgdg-common: [Errno 256] No more mirrors to try.
https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-7-aarch64/repodata/repomd.xml:
[Errno -1] repomd.xml signature could not be verified for pgdg-common

中止

PostgreSQLのユーザ会?でRPM配ってるみたいなのでそれ試してみる

ここからwgetするだけ

Index of /pub/repos/yum/12/redhat/rhel-7-aarch64/

現時点最新15.3のをインストールしたらエラーでたので

# ls -Ahl
total 1.9M
-rw-r--r-- 1 root root 1.6M May 11 06:25 postgresql15-15.3-1PGDG.rhel7.aarch64.rpm
-rw-r--r-- 1 root root 269K May 11 06:25 postgresql15-libs-15.3-1PGDG.rhel7.aarch64.rpm
# rpm -ivh *
warning: postgresql15-15.3-1PGDG.rhel7.aarch64.rpm: Header V4 RSA/SHA1 Signature, key ID 69246c03: NOKEY
error: Failed dependencies:
        libzstd >= 1.4.0 is needed by postgresql15-15.3-1PGDG.rhel7.aarch64
        libzstd.so.1()(64bit) is needed by postgresql15-15.3-1PGDG.rhel7.aarch64

12をインストール

# ls -Ahl
total 2.0M
-rw-r--r-- 1 root root 1.7M May 11 05:32 postgresql12-12.15-1PGDG.rhel7.aarch64.rpm
-rw-r--r-- 1 root root 364K May 11 05:32 postgresql12-libs-12.15-1PGDG.rhel7.aarch64.rpm
# rpm -ivh *
warning: postgresql12-12.15-1PGDG.rhel7.aarch64.rpm: Header V4 RSA/SHA1 Signature, key ID 69246c03: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:postgresql12-libs-12.15-1PGDG.rhe################################# [ 50%]
   2:postgresql12-12.15-1PGDG.rhel7   ################################# [100%]

おー、つながった

こういうのは別記事にして、qiitaとかみんなに見てもらえるメディアにのせたほうが役に立ちそう

->書いた(このアカウントで初投稿)

psql: SCRAM authentication requires libpq version 10 or above のクライアント側の簡単な対処(PostgreSQL12のpsqlをインストール) – Qiita

以降、psqlでつなぐ

100万件select文の実行計画確認

set search_path to "PFS";
explain (analyze, buffers) select * from t1;
                                                 QUERY PLAN

----------------------------------------------------------------------------------------------
---------------
 Seq Scan on t1  (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.003..44.923 rows=10
00000 loops=1)
   Buffers: shared hit=4425
 Planning:
   Buffers: shared hit=19
 Planning Time: 0.127 ms
 Execution Time: 79.971 ms
(6 rows)

shared hit=4425。これはブロック数か何か?? PostgreSQLのセグメント格納方式知らないけど..

statistics見る

Heap Blocks readが4425だから、全部キャッシュから取れてるってことかな。

インデックスアクセスしてみる

create index i1 on t1(c1);

再度普通に全件選択

インデックス未使用

 Seq Scan on t1  (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.004..46.975 rows=10
00000 loops=1)
   Buffers: shared hit=4425
 Planning:
   Buffers: shared hit=20
 Planning Time: 0.113 ms
 Execution Time: 82.263 ms
(6 rows)

1カラムだけ指定してみる

explain (analyze, buffers) select * from t1 where c1=1;

 Index Only Scan using i1 on t1  (cost=0.42..4.44 rows=1 width=4) (actual time=0.024..0.025 ro
ws=1 loops=1)
   Index Cond: (c1 = 1)
   Heap Fetches: 0
   Buffers: shared hit=4
 Planning:
   Buffers: shared hit=8
 Planning Time: 0.074 ms
 Execution Time: 0.049 ms
(8 rows)

インデックス使われた。

インデックス利用状況の確認SQLがある

PostgreSQLの運用でよく使うクエリカンペ - Qiita
select * from pg_stat_user_indexes;

 relid | indexrelid | schemaname | relname | indexrelname | idx_scan | idx_tup_read | idx_tup_
fetch
-------+------------+------------+---------+--------------+----------+--------------+---------
------
 16444 |      16447 | PFS        | t1      | i1           |        1 |            1 |
    0

情報少な..

これ直近1回の結果だろうか??再実行

PFS=> explain (analyze, buffers) select * from t1 where c1=1;
                                                 QUERY PLAN

----------------------------------------------------------------------------------------------
--------------
 Index Only Scan using i1 on t1  (cost=0.42..4.44 rows=1 width=4) (actual time=0.025..0.026 ro
ws=1 loops=1)
   Index Cond: (c1 = 1)
   Heap Fetches: 0
   Buffers: shared hit=4
 Planning Time: 0.067 ms
 Execution Time: 0.046 ms
(6 rows)

PFS=>
select * from pg_stat_user_indexes;
 relid | indexrelid | schemaname | relname | indexrelname | idx_scan | idx_tup_read | idx_tup_
fetch
-------+------------+------------+---------+--------------+----------+--------------+---------
------
 16444 |      16447 | PFS        | t1      | i1           |        2 |            2 |
    0
(1 row)

idx_scan/idx_tup_readが2になったので、インデックスごとに、そのインデックスの累積値を出すっぽいな.. 運用でよく使うとして紹介されてるけど、これの有用性は今の自分にはまだわかっていない

あとポスグレって、インデックス貼った時にoracleみたいに統計情報取る必要ないのかな??

いまはインデックス貼るだけで実行計画変化したけど。

統計見てみる

参考サイト

https://changineer.info/server/postgresql/postgresql_auto_analyze.html
PFS=> \x
Expanded display is on.
PFS=> SELECT * FROM pg_stat_all_tables where relname ='t1';
-[ RECORD 1 ]-------+------------------------------
relid               | 16444
schemaname          | PFS
relname             | t1
seq_scan            | 9
seq_tup_read        | 7000000
idx_scan            | 2
idx_tup_fetch       | 0
n_tup_ins           | 1000000
n_tup_upd           | 0
n_tup_del           | 0
n_tup_hot_upd       | 0
n_live_tup          | 1000000
n_dead_tup          | 0
n_mod_since_analyze | 0
n_ins_since_vacuum  | 0
last_vacuum         |
last_autovacuum     | 2023-07-13 21:45:13.436876+00
last_analyze        |
last_autoanalyze    | 2023-07-13 21:45:13.603786+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 0
autoanalyze_count   | 1

last_autoanalyzeは昨日の日付、last_analyzeはnull。

これは統計は昨日のままで直近では取れてないと思って良いだろうか..

pg_stat_statementsというのものがあるので試してみる

参考サイト

postgresqlでpg_stat_statementsを使ってSlow Queryを調べる - Qiita
select name, comment from pg_available_extensions order by 1;
             name             |                                                       comment
------------------------------+---------------------------------------------------------------------------------------------------------------------
 address_standardizer         | Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.
 address_standardizer_data_us | Address Standardizer US dataset example
 amcheck                      | functions for verifying relation integrity
 apg_plan_mgmt                | Amazon Aurora with PostgreSQL compatibility Query Plan Management
 aurora_stat_utils            | Statistics utility functions
 autoinc                      | functions for autoincrementing fields
 aws_commons                  | Common data types across AWS services
 aws_lambda                   | AWS Lambda integration
 aws_ml                       | ml integration
 aws_s3                       | AWS S3 extension for importing data from S3
 babelfishpg_common           | Transact SQL Datatype Support
 babelfishpg_money            | babelfishpg_money
 babelfishpg_tds              | TDS protocol extension
 babelfishpg_telemetry        | Transact SQL Telemetry
 babelfishpg_tsql             | Transact SQL compatibility
 bloom                        | bloom access method - signature file based index
 bool_plperl                  | transform between bool and plperl
 btree_gin                    | support for indexing common datatypes in GIN
 btree_gist                   | support for indexing common datatypes in GiST
 citext                       | data type for case-insensitive character strings
 cube                         | data type for multidimensional cubes
 dblink                       | connect to other PostgreSQL databases from within a database
 dict_int                     | text search dictionary template for integers
 dict_xsyn                    | text search dictionary template for extended synonym processing
 earthdistance                | calculate great-circle distances on the surface of the Earth
 fuzzystrmatch                | determine similarities and distance between strings
 hll                          | type for storing hyperloglog data
 hstore                       | data type for storing sets of (key, value) pairs
 hstore_plperl                | transform between hstore and plperl
 insert_username              | functions for tracking who changed a table
 intagg                       | integer aggregator and enumerator (obsolete)
 intarray                     | functions, operators, and index support for 1-D arrays of integers
 ip4r                         |
 isn                          | data types for international product numbering standards
 jsonb_plperl                 | transform between jsonb and plperl
 lo                           | Large Object maintenance
 log_fdw                      | foreign-data wrapper for Postgres log file access
 ltree                        | data type for hierarchical tree-like structures
 moddatetime                  | functions for tracking last modification time
 old_snapshot                 | utilities in support of old_snapshot_threshold
 oracle_fdw                   | foreign data wrapper for Oracle access
 orafce                       | Functions and operators that emulate a subset of functions and packages from the Oracle RDBMS
 pg_bigm                      | text similarity measurement and index searching based on bigrams
 pg_buffercache               | examine the shared buffer cache
 pg_cron                      | Job scheduler for PostgreSQL
 pg_freespacemap              | examine the free space map (FSM)
 pg_hint_plan                 |
 pg_partman                   | Extension to manage partitioned tables by time or ID
 pg_prewarm                   | prewarm relation data
 pg_proctab                   | Access operating system process table
 pg_repack                    | Reorganize tables in PostgreSQL databases with minimal locks
 pg_similarity                | support similarity queries
 pg_stat_statements           | track planning and execution statistics of all SQL statements executed
 pg_tle                       | Trusted Language Extensions for PostgreSQL
 pg_trgm                      | text similarity measurement and index searching based on trigrams
 pg_visibility                | examine the visibility map (VM) and page-level visibility info
 pg_walinspect                | functions to inspect contents of PostgreSQL Write-Ahead Log
 pgaudit                      | provides auditing functionality
 pgcrypto                     | cryptographic functions
 pglogical                    | PostgreSQL Logical Replication
 pglogical_origin             | Dummy extension for compatibility when upgrading from Postgres 9.4
 pgrouting                    | pgRouting Extension
 pgrowlocks                   | show row-level locking information
 pgstattuple                  | show tuple-level statistics
 pgtap                        | Unit testing for PostgreSQL
 plcoffee                     | PL/CoffeeScript (v8) trusted procedural language
 plls                         | PL/LiveScript (v8) trusted procedural language
 plperl                       | PL/Perl procedural language
 plpgsql                      | PL/pgSQL procedural language
 plprofiler                   | server-side support for profiling PL/pgSQL functions
 pltcl                        | PL/Tcl procedural language
 plv8                         | PL/JavaScript (v8) trusted procedural language
 postgis                      | PostGIS geometry and geography spatial types and functions
 postgis_raster               | PostGIS raster types and functions
 postgis_tiger_geocoder       | PostGIS tiger geocoder and reverse geocoder
 postgis_topology             | PostGIS topology spatial types and functions
 postgres_fdw                 | foreign-data wrapper for remote PostgreSQL servers
 prefix                       | Prefix Range module for PostgreSQL
 rdkit                        | Cheminformatics functionality for PostgreSQL.
 rds_activity_stream          | RDS ACTIVITY Agent
 rds_tools                    | miscellaneous administrative functions for Aurora PostgreSQL
 refint                       | functions for implementing referential integrity (obsolete)
 seg                          | data type for representing line segments or floating-point intervals
 sslinfo                      | information about SSL certificates
 tablefunc                    | functions that manipulate whole tables, including crosstab
 tcn                          | Triggered change notifications
 tds_fdw                      | Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)
 tsm_system_rows              | TABLESAMPLE method which accepts number of rows as a limit
 tsm_system_time              | TABLESAMPLE method which accepts time in milliseconds as a limit
 unaccent                     | text search dictionary that removes accents
 uuid-ossp                    | generate universally unique identifiers (UUIDs)
 vector                       | vector data type and ivfflat access method
(92 rows)

利用可能、なものはいっぱいある.. (Aurora PostgreSQL 15.3)

頑張って全体を理解してみる

めっちゃ簡単に整形できたよ.. すご

手順)

  • コンソールを全画面化して変な改行入れないように再実行
  • 出力結果をsakuraにコピペして不要な行(区切り文字だけの行)消すとか整形
  • libreofficeに貼る。貼るときに区切り文字を「|」で設定するとちゃんと表になる
  • comment列をコピーしてGoogle翻訳
  • Google翻訳結果をコピーして表に戻す(ちゃんと元々のセルの位置に戻る)
  • libreofficeのその表をコピーしてWordPressに貼るだけ(できたのが以下)
  • MLがミリリットルに翻訳されてるのとか見つけて修正
namecomment
address_standardizer住所を構成要素に解析するために使用されます。 通常、ジオコーディング住所正規化ステップをサポートするために使用されます。
address_standardizer_data_usAddress Standardizer US データセットの例
amcheck関係の整合性を検証するための関数
apg_plan_mgmtPostgreSQL との互換性を備えた Amazon Aurora クエリプラン管理
aurora_stat_utils統計ユーティリティ関数
autoincフィールドを自動インクリメントする関数
aws_commonsAWS のサービス全体で共通のデータ型
aws_lambdaAWS Lambda の統合
aws_mlML統合
aws_s3S3 からデータをインポートするための AWS S3 拡張機能
babelfishpg_commonトランザクション SQL データ型のサポート
babelfishpg_moneybabelfishpg_money
babelfishpg_tdsTDSプロトコル拡張
babelfishpg_telemetryトランザクション SQL テレメトリ
babelfishpg_tsqlトランザクション SQL の互換性
bloomブルームアクセス方法 – 署名ファイルベースのインデックス
bool_plperlbool と plperl 間の変換
btree_ginGIN での一般的なデータ型のインデックス作成のサポート
btree_gistGiST での一般的なデータ型のインデックス作成のサポート
citext大文字と小文字を区別しない文字列のデータ型
cube多次元キューブのデータ型
dblinkデータベース内から他の PostgreSQL データベースに接続する
dict_int整数用のテキスト検索辞書テンプレート
dict_xsyn拡張同義語処理用のテキスト検索辞書テンプレート
earthdistance地球表面の大圏距離を計算する
fuzzystrmatch文字列間の類似性と距離を決定する
hllhyperloglog データを保存するためのタイプ
hstore(キー、値) ペアのセットを格納するためのデータ型
hstore_plperlhstore と plperl 間の変換
insert_username誰がテーブルを変更したかを追跡する関数
intagg整数アグリゲータと列挙子 (廃止)
intarray整数の 1 次元配列の関数、演算子、およびインデックスのサポート
ip4r
isn国際的な製品番号付け標準のデータ型
jsonb_plperljsonb と plperl の間で変換する
loラージオブジェクトのメンテナンス
log_fdwPostgres ログ ファイル アクセス用の外部データ ラッパー
ltree階層ツリー状構造のデータ型
moddatetime最終変更時刻を追跡するための関数
old_snapshotold_snapshot_threshold をサポートするユーティリティ
oracle_fdwOracle アクセス用の外部データ ラッパー
orafceOracle RDBMS の関数とパッケージのサブセットをエミュレートする関数と演算子
pg_bigmテキストの類似性測定とバイグラムに基づくインデックス検索
pg_buffercache共有バッファキャッシュを調べる
pg_cronPostgreSQL のジョブ スケジューラ
pg_freespacemap空き領域マップ (FSM) を調べる
pg_hint_plan
pg_partmanパーティション化されたテーブルを時間または ID で管理するための拡張機能
pg_prewarmウォーム前の関係データ
pg_proctabオペレーティング システムのプロセス テーブルにアクセスする
pg_repack最小限のロックで PostgreSQL データベースのテーブルを再編成する
pg_similarity類似性クエリのサポート
pg_stat_statements実行されたすべての SQL ステートメントの計画と実行統計を追跡する
pg_tlePostgreSQL 用の信頼できる言語拡張機能
pg_trgmテキストの類似性測定とトリグラムに基づくインデックス検索
pg_visibility可視性マップ (VM) とページレベルの可視性情報を調べる
pg_walinspectPostgreSQL 先行書き込みログの内容を検査する関数
pgaudit監査機能を提供します
pgcrypto暗号化機能
pglogicalPostgreSQL 論理レプリケーション
pglogical_originPostgres 9.4 からアップグレードする場合の互換性のためのダミー拡張機能
pgroutingpgRouting 拡張機能
pgrowlocks行レベルのロック情報を表示する
pgstattupleタプルレベルの統計を表示する
pgtapPostgreSQL の単体テスト
plcoffeePL/CoffeeScript (v8) 信頼できる手続き型言語
pllsPL/LiveScript (v8) 信頼できる手続き型言語
plperlPL/Perl手続き型言語
plpgsqlPL/pgSQL手続き型言語
plprofilerPL/pgSQL関数のプロファイリングに対するサーバー側のサポート
pltclPL/Tcl 手続き型言語
plv8PL/JavaScript (v8) 信頼できる手続き型言語
postgisPostGIS のジオメトリと地理の空間タイプと関数
postgis_rasterPostGIS ラスターのタイプと関数
postgis_tiger_geocoderPostGIS Tiger ジオコーダーとリバース ジオコーダー
postgis_topologyPostGIS トポロジの空間タイプと機能
postgres_fdwリモート PostgreSQL サーバーの外部データ ラッパー
prefixPostgreSQL のプレフィックス範囲モジュール
rdkitPostgreSQL のケモインフォマティクス機能。
rds_activity_streamRDS アクティビティ エージェント
rds_toolsAurora PostgreSQL のその他の管理機能
refint参照整合性を実装するための関数 (廃止)
seg線分または浮動小数点間隔を表すデータ型
sslinfoSSL証明書に関する情報
tablefuncクロス集計を含むテーブル全体を操作する関数
tcnトリガーによる変更通知
tds_fdwTDS データベース (Sybase または Microsoft SQL Server) をクエリするための外部データ ラッパー
tsm_system_rows行数を制限として受け入れる TABLESAMPLE メソッド
tsm_system_timeミリ秒単位の時間を制限として受け入れる TABLESAMPLE メソッド
unaccentアクセントを削除するテキスト検索辞書
uuid-ossp汎用一意識別子 (UUID) を生成する
vectorベクトル データ型と ivfflat アクセス方法

この中でパフォーマンス系に絞ると以下

namecomment
apg_plan_mgmtPostgreSQL との互換性を備えた Amazon Aurora クエリプラン管理
aurora_stat_utils統計ユーティリティ関数
pg_buffercache共有バッファキャッシュを調べる
pg_hint_plan
pg_prewarmウォーム前の関係データ
pg_stat_statements実行されたすべての SQL ステートメントの計画と実行統計を追跡する
pg_visibility可視性マップ (VM) とページレベルの可視性情報を調べる
pg_walinspectPostgreSQL 先行書き込みログの内容を検査する関数
pgrowlocks行レベルのロック情報を表示する
pgstattupleタプルレベルの統計を表示する

パフォーマンス系じゃないかもだけどなんか気になるものを念のため以下に残しとく(気が向いたら調べる)

namecomment
aws_mlML統合
loラージオブジェクトのメンテナンス
pg_partmanパーティション化されたテーブルを時間または ID で管理するための拡張機能
pg_proctabオペレーティング システムのプロセス テーブルにアクセスする
pg_repack最小限のロックで PostgreSQL データベースのテーブルを再編成する
pgroutingpgRouting 拡張機能
pg_similarity類似性クエリのサポート
rds_activity_streamRDS アクティビティ エージェント
rds_toolsAurora PostgreSQL のその他の管理機能
tablefuncクロス集計を含むテーブル全体を操作する関数
tsm_system_rows行数を制限として受け入れる TABLESAMPLE メソッド
tsm_system_timeミリ秒単位の時間を制限として受け入れる TABLESAMPLE メソッド

んで、話は戻って、pg_stat_statementsを使えるようにする

参考サイト

インストール

PFS=> select * from pg_available_extensions where name = 'pg_stat_statements';
        name        | default_version | installed_version |                                c
omment
--------------------+-----------------+-------------------+---------------------------------
---------------------------------------
 pg_stat_statements | 1.10            |                   | track planning and execution sta
tistics of all SQL statements executed
(1 row)

PFS=>
PFS=> CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION
PFS=>
PFS=> select * from pg_available_extensions where name = 'pg_stat_statements';
        name        | default_version | installed_version |                                c
omment
--------------------+-----------------+-------------------+---------------------------------
---------------------------------------
 pg_stat_statements | 1.10            | 1.10              | track planning and execution sta
tistics of all SQL statements executed
(1 row)

使えるようになった

けどレコード多いな

PFS=> select count(*) from pg_stat_statements;
 count
-------
  4774
(1 row)

直近で自分が実行したSQLに絞るには..?

pg_stat_statementsのカラム一覧

PFS=> \d pg_stat_statements
                       View "PFS.pg_stat_statements"
         Column         |       Type       | Collation | Nullable | Default
------------------------+------------------+-----------+----------+---------
 userid                 | oid              |           |          |
 dbid                   | oid              |           |          |
 toplevel               | boolean          |           |          |
 queryid                | bigint           |           |          |
 query                  | text             |           |          |
 plans                  | bigint           |           |          |
 total_plan_time        | double precision |           |          |
 min_plan_time          | double precision |           |          |
 max_plan_time          | double precision |           |          |
 mean_plan_time         | double precision |           |          |
 stddev_plan_time       | double precision |           |          |
 calls                  | bigint           |           |          |
 total_exec_time        | double precision |           |          |
 min_exec_time          | double precision |           |          |
 max_exec_time          | double precision |           |          |
 mean_exec_time         | double precision |           |          |
 stddev_exec_time       | double precision |           |          |
 rows                   | bigint           |           |          |
 shared_blks_hit        | bigint           |           |          |
 shared_blks_read       | bigint           |           |          |
 shared_blks_dirtied    | bigint           |           |          |
 shared_blks_written    | bigint           |           |          |
 local_blks_hit         | bigint           |           |          |
 local_blks_read        | bigint           |           |          |
 local_blks_dirtied     | bigint           |           |          |
 local_blks_written     | bigint           |           |          |
 temp_blks_read         | bigint           |           |          |
 temp_blks_written      | bigint           |           |          |
 blk_read_time          | double precision |           |          |
 blk_write_time         | double precision |           |          |
 temp_blk_read_time     | double precision |           |          |
 temp_blk_write_time    | double precision |           |          |
 wal_records            | bigint           |           |          |
 wal_fpi                | bigint           |           |          |
 wal_bytes              | numeric          |           |          |
 jit_functions          | bigint           |           |          |
 jit_generation_time    | double precision |           |          |
 jit_inlining_count     | bigint           |           |          |
 jit_inlining_time      | double precision |           |          |
 jit_optimization_count | bigint           |           |          |
 jit_optimization_time  | double precision |           |          |
 jit_emission_count     | bigint           |           |          |
 jit_emission_time      | double precision |           |          |

クエリで絞れた

select * from pg_stat_statements where query like '%t1%';

1つだけに絞って縦表示で見てみる

\x
select * from pg_stat_statements where query like 'explain (analyze, buffers) select * from t1 where c1=1';
PFS=> \x
Expanded display is on.
PFS=> select * from pg_stat_statements where query like 'explain (analyze, buffers) select * from t1 where c1=1';
-[ RECORD 1 ]----------+-------------------------------------------------------
userid                 | 16400
dbid                   | 16401
toplevel               | t
queryid                | 6415160146743782283
query                  | explain (analyze, buffers) select * from t1 where c1=1
plans                  | 0
total_plan_time        | 0
min_plan_time          | 0
max_plan_time          | 0
mean_plan_time         | 0
stddev_plan_time       | 0
calls                  | 2
total_exec_time        | 0.980962
min_exec_time          | 0.178104
max_exec_time          | 0.802858
mean_exec_time         | 0.490481
stddev_exec_time       | 0.312377
rows                   | 0
shared_blks_hit        | 19
shared_blks_read       | 0
shared_blks_dirtied    | 0
shared_blks_written    | 0
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
temp_blk_read_time     | 0
temp_blk_write_time    | 0
wal_records            | 0
wal_fpi                | 0
wal_bytes              | 0
jit_functions          | 0
jit_generation_time    | 0
jit_inlining_count     | 0
jit_inlining_time      | 0
jit_optimization_count | 0
jit_optimization_time  | 0
jit_emission_count     | 0
jit_emission_time      | 0

情報取れた。今のところどの辺が有用な値なのかはわかっていない。

もちっとちゃんとしたパフォーマンステスト用データ投入

ポイントカードをイメージする

顧客テーブル

ID, 氏名, 誕生日, 性別, 住んでる県

create table pfs.customer(cardnumber integer, name varchar(20), birthday date, gender integer, state varchar(20));

商品テーブル

ID, 商品名, 価格, カテゴリ, メーカー

create table pfs.item(itemid integer, name varchar(20), price integer, category varchar(20), manufacturer varchar(20));

店舗テーブル

店舗ID, 店舗名, 県

create table pfs.shop(shopid integer, shopname varchar(20), state varchar(20));

購入履歴テーブル

購入ID, カードNo, 商品ID, ショップID, 個数, 購入日

カードNo, 商品ID, ショップIDは他テーブルを参照する (外部キーは利用しない。SQLで整合性取る)

create table pfs.purchase(purchaseid integer, cardnumber integer, itemid integer, shopid integer, quantity integer, purchasedate date);

できたもの

pfs=> \d pfs.customer
                        Table "pfs.customer"
   Column   |         Type          | Collation | Nullable | Default
------------+-----------------------+-----------+----------+---------
 cardnumber | integer               |           |          |
 name       | character varying(20) |           |          |
 birthday   | date                  |           |          |
 gender     | integer               |           |          |
 state      | character varying(20) |           |          |

pfs=> \d pfs.item
                           Table "pfs.item"
    Column    |         Type          | Collation | Nullable | Default
--------------+-----------------------+-----------+----------+---------
 itemid       | integer               |           |          |
 name         | character varying(20) |           |          |
 price        | integer               |           |          |
 category     | character varying(20) |           |          |
 manufacturer | character varying(20) |           |          |

pfs=> \d pfs.shop
                         Table "pfs.shop"
  Column  |         Type          | Collation | Nullable | Default
----------+-----------------------+-----------+----------+---------
 shopid   | integer               |           |          |
 shopname | character varying(20) |           |          |
 state    | character varying(20) |           |          |

pfs=> \d pfs.purchase
                  Table "pfs.purchase"
    Column    |  Type   | Collation | Nullable | Default
--------------+---------+-----------+----------+---------
 purchaseid   | integer |           |          |
 cardnumber   | integer |           |          |
 itemid       | integer |           |          |
 shopid       | integer |           |          |
 quantity     | integer |           |          |
 purchasedate | date    |           |          |

プライマリーキーとか制約(ユニーク, null許可), インデックス貼るのとかやらないと..

データ投入面倒そうだなあ

apg_plan_mgmt

実行計画の固定化機能。クラスメソッドさんの記事のとおりな感じ

Aurora PostgreSQLのクエリ実行計画管理機能を試してみた | DevelopersIO

aurora_stat_utils

aurora_wait_report - Amazon Aurora

この関数は、aurora_stat_system_waits() 関数と pg_stat_database PostgreSQL 統計ビューからの統計データの 2 つのスナップショットを比較することにより、インスタンスレベルの待機イベントを計算します。

インストールする

pfs=> select * from pg_available_extensions where name = 'aurora_stat_utils';
       name        | default_version | installed_version |           comment
-------------------+-----------------+-------------------+------------------------------
 aurora_stat_utils | 1.0             |                   | Statistics utility functions
(1 row)

pfs=> select * from pg_available_extensions where name = 'aurora_stat_utils';

pfs=> CREATE extension aurora_stat_utils;
CREATE EXTENSION
pfs=> select * from pg_available_extensions where name = 'aurora_stat_utils';
       name        | default_version | installed_version |           comment
-------------------+-----------------+-------------------+------------------------------
 aurora_stat_utils | 1.0             | 1.0               | Statistics utility functions
(1 row)

使ってみる

pfs-> SELECT * FROM aurora_wait_report();

NOTICE:  committed 31 transactions in 10 seconds (tps 3)
 type_name |        event_name        | waits | wait_time | ms_per_wait | waits_per_xact | m
s_per_xact
-----------+--------------------------+-------+-----------+-------------+----------------+--
-----------
 Client    | ClientRead               |    40 |  30989.00 |     774.725 |           1.29 |
   999.645
 Timeout   | PgSleep                  |   400 |  20074.86 |      50.187 |          12.90 |
   647.576
 Activity  | BgWriterHibernate        |     2 |  13101.69 |    6550.845 |           0.06 |
   422.635
 Activity  | WalWriterMain            |    50 |  10047.61 |     200.952 |           1.61 |
   324.116
 Activity  | AutoVacuumMain           |    24 |  10005.42 |     416.892 |           0.77 |
   322.755
 Activity  | BgWriterMain             |     1 |    201.01 |     201.011 |           0.03 |
     6.484
 IO        | XactSync                 |    15 |     43.45 |       2.897 |           0.48 |
     1.402
 IO        | RelationMapRead          |    16 |      0.51 |       0.032 |           0.52 |
     0.016
 IO        | AuroraStorageLogAllocate |    77 |      0.15 |       0.002 |           2.48 |
     0.005
(9 rows)

単に実行すると10秒間の待機レポートとなる。

60秒で取るには60を指定すれば良い

実行に時間かかるのか..? と思ったけど、これ実行開始してから、指定秒数待ってるのか..

つまりリアルタイムのものを取る..? 1秒にしたら1秒で返ってくるし

pfs=> SELECT * FROM aurora_wait_report(60);

NOTICE:  committed 260 transactions in 60 seconds (tps 4)
 type_name |        event_name        | waits | wait_time | ms_per_wait | waits_per_xact | m
s_per_xact
-----------+--------------------------+-------+-----------+-------------+----------------+--
-----------
 Client    | ClientRead               |   354 | 292838.78 |     827.228 |           1.36 |
  1126.303
 Activity  | LogicalLauncherMain      |     1 | 180099.87 |  180099.872 |           0.00 |
   692.692
 Timeout   | PgSleep                  |  2389 | 120115.46 |      50.279 |           9.19 |
   461.983
 Activity  | BgWriterHibernate        |     7 |  63319.74 |    9045.677 |           0.03 |
   243.537
 Activity  | WalWriterMain            |   300 |  60276.48 |     200.922 |           1.15 |
   231.833
 Activity  | CheckpointerMain         |     1 |  60099.68 |   60099.675 |           0.00 |
   231.153
 Activity  | AutoVacuumMain           |   138 |  60048.72 |     435.136 |           0.53 |
   230.957
 Activity  | BgWriterMain             |     6 |   1205.42 |     200.903 |           0.02 |
     4.636
 IO        | XactSync                 |    91 |    261.67 |       2.875 |           0.35 |
     1.006
 IO        | RelationMapRead          |    96 |      3.32 |       0.035 |           0.37 |
     0.013
 IO        | AuroraStorageLogAllocate |   241 |      0.82 |       0.003 |           0.93 |
     0.003
 IO        | DataFileExtend           |     1 |      0.02 |       0.015 |           0.00 |
     0.000
 IO        | ControlFileWriteUpdate   |     2 |      0.02 |       0.009 |           0.01 |
     0.000
 IO        | ControlFileSyncUpdate    |     1 |      0.00 |       0.001 |           0.00 |
     0.000
(14 rows)

まあこれでDBの待機イベントトップは分かるか..

リアルタイム実行なので、定期取得しておかないと、あとから分からなそう

pg_buffercache

F.27. pg_buffercache

インストール

pfs=> create table pfs.customer(id integer, name varchar(20), birthday date, gender integer, state varchar(20));^C
pfs=>
pfs=> select * from pg_available_extensions where name = 'pg_buffercache';
      name      | default_version | installed_version |             comment
----------------+-----------------+-------------------+---------------------------------
 pg_buffercache | 1.3             |                   | examine the shared buffer cache
(1 row)

pfs=> CREATE EXTENSION pg_buffercache;
CREATE EXTENSION
pfs=>
pfs=> select * from pg_available_extensions where name = 'pg_buffercache';
      name      | default_version | installed_version |             comment
----------------+-----------------+-------------------+---------------------------------
 pg_buffercache | 1.3             | 1.3               | examine the shared buffer cache
(1 row)

使ってみる

件数確認

pfs=> select count(*) from pg_buffercache;
  count
---------
 1301958
(1 row)

10件だけ見てみる

pfs=> select * from pg_buffercache FETCH FIRST 10 ROWS ONLY;
 bufferid | relfilenode | reltablespace | reldatabase | relforknumber | relblocknumber | isdirty | usagecount | pi
nning_backends
----------+-------------+---------------+-------------+---------------+----------------+---------+------------+---
---------------
        1 |        1262 |          1664 |           0 |             0 |              0 | f       |          5 |
             0
        2 |        1260 |          1664 |           0 |             0 |              0 | f       |          5 |
             0
        3 |        1259 |          1663 |       16384 |             0 |              0 | f       |          5 |
             0
        4 |        1259 |          1663 |       16384 |             0 |              1 | f       |          5 |
             0
        5 |        1259 |          1663 |       16384 |             0 |              2 | f       |          5 |
             0
        6 |        1259 |          1663 |       16384 |             0 |              3 | f       |          5 |
             0
        7 |        1249 |          1663 |       16384 |             0 |              0 | f       |          5 |
             0
        8 |        1249 |          1663 |       16384 |             0 |              1 | f       |          5 |
             0
        9 |        1249 |          1663 |       16384 |             0 |              2 | f       |          5 |
             0
       10 |        1249 |          1663 |       16384 |             0 |              3 | f       |          5 |
             0
pfs=>

なるほど、バッファキャッシュがID管理されてて、IDごとにバッファキャッシュにのせてるものを一覧できると。

リファレンスより、以下部分で、reltablespace/reldatabaseのOIDをpg_class/pg_databaseと紐づけると、テーブル/インデックス名を拾える。

サンプルを実行してみる

SELECT n.nspname, c.relname, count(*) AS buffers
             FROM pg_buffercache b JOIN pg_class c
             ON b.relfilenode = pg_relation_filenode(c.oid) AND
                b.reldatabase IN (0, (SELECT oid FROM pg_database
                                      WHERE datname = current_database()))
             JOIN pg_namespace n ON n.oid = c.relnamespace
             GROUP BY n.nspname, c.relname
             ORDER BY 3 DESC
             LIMIT 10;

pfs=> SELECT n.nspname, c.relname, count(*) AS buffers
pfs->              FROM pg_buffercache b JOIN pg_class c
pfs->              ON b.relfilenode = pg_relation_filenode(c.oid) AND
pfs->                 b.reldatabase IN (0, (SELECT oid FROM pg_database
pfs(>                                       WHERE datname = current_database()))
pfs->              JOIN pg_namespace n ON n.oid = c.relnamespace
pfs->              GROUP BY n.nspname, c.relname
pfs->              ORDER BY 3 DESC
pfs->              LIMIT 10;
  nspname   |            relname             | buffers
------------+--------------------------------+---------
 pg_catalog | pg_proc                        |     100
 pg_toast   | pg_toast_2618                  |      68
 pg_catalog | pg_attribute                   |      62
 pg_catalog | pg_description                 |      48
 pg_catalog | pg_collation                   |      37
 pg_catalog | pg_proc_proname_args_nsp_index |      31
 pg_catalog | pg_description_o_c_o_index     |      28
 pg_catalog | pg_statistic                   |      25
 pg_catalog | pg_type                        |      19
 pg_catalog | pg_depend                      |      18
(10 rows)

なるほどなあ。

これも、定期取得しておけば、パフォーマンス問題(処理時間長いかつディスク負荷が高い)が起きた時に、キャッシュヒット率の低下がひとつの要因かが分かりそう。

バッファキャッシュを簡単に確認できるのは、oracleより簡単な感じでいいなあ(oracleでもv$bfでできるけど、公式な方法じゃなかったと思うのと、SQLが重め)。

buffersはブロック?単位で表示されてるけど、これバイト表記にできるのかな??

また気が向いたらやる

pg_hint_plan

インストール

pfs=> select * from pg_available_extensions where name = 'pg_hint_plan';
     name     | default_version | installed_version | comment
--------------+-----------------+-------------------+---------
 pg_hint_plan | 1.5             |                   |
(1 row)

pfs=> CREATE extension pg_hint_plan;
CREATE EXTENSION
pfs=>
pfs=> select * from pg_available_extensions where name = 'pg_hint_plan';
     name     | default_version | installed_version | comment
--------------+-----------------+-------------------+---------
 pg_hint_plan | 1.5             | 1.5               |
(1 row)

ヒント句。

pg_prewarm

インストール

pfs=> select * from pg_available_extensions where name = 'pg_prewarm';
    name    | default_version | installed_version |        comment
------------+-----------------+-------------------+-----------------------
 pg_prewarm | 1.2             |                   | prewarm relation data
(1 row)

pfs=> CREATE extension pg_prewarm;
CREATE EXTENSION
pfs=>
pfs=> select * from pg_available_extensions where name = 'pg_prewarm';
    name    | default_version | installed_version |        comment
------------+-----------------+-------------------+-----------------------
 pg_prewarm | 1.2             | 1.2               | prewarm relation data
(1 row)

構文

SELECT     pg_prewarm('テーブル名', 'buffer', 'main');

実行してみる