なからなLife

geekに憧れと敬意を抱きながら、SE、ITコンサル、商品企画、事業企画、管理会計、総務・情シス、再び受託でDB屋さんと流浪する人のブログです。

RDSがAuroraより速い!?について調べてみた

長くなりそうなので、先に要点だけ。

Twitter


に連なる一連のツイートに結構反応があったので、ブログにもまとめておきます。

  • RDS PostgreSQLの方がAurora PostgreSQLより速いぜ!って記事を見かけたけど、大量データを1クライアントで流し込む試験の結果だった。
  • 複数クライアントからのOLTPワークロードでもRDSの方が速いパターンってあるのかな?TPC-Cで試してみよう!
  • インスタンスのサイズ(vCPU)と同時実行数によって、RDSの方が速いケース、Auroraの方が速いケースがあった。
  • 処理の多重度が低いとRDSの方が速いケースがあるけど、実用的なサイズと多重度だと、概ねAuroraの方が速いと思っていて良さそう!
  • 結局、実際にどんなワークロードを実行するか次第なので、ちゃんと実機で試そうぜ。


というわけで、以下詳細。

調査のきっかけ

Twitterを眺めていたら、「AuroraよりRDSの方が速かった」というブログ記事がシェアされてきて、AWSの謳い文句*1とも違うし、実体験ベースでもAuroraのほうが速い印象があったので違和感を持って該当記事にあたってみました。


medium.datadriveninvestor.com

TLDR: To get the best I/O speed, use regular RDS Postgres with a big (General Purpose) SSD disk.

Google翻訳
TLDR:最高のI / O速度を得るには、大きな(汎用)SSDディスクで通常のRDS Postgresを使用します。

まとめだけ見ると、確かにそのように書いてあります。


この記事は、ちゃんと読んでいくと、とても丁寧に試験条件が説明されており、TPC系ではない独自のワークロードを用いて計測し、実際に使用したスクリプトGithubでも公開されています。


それによると、Methodologyの2番目に

Insert 100 millions rows in 5 batches with a constant content, with a total size of 16 GB.

Google翻訳
合計サイズが16GBで、コンテンツが一定の5つのバッチに1億行を挿入します。

とあります。


Github上のソースを見ても、たしかに1つのスクリプトの中で、generate_series(1, 2E7)つまり20,000,000件*5回のINSERTによって1億行を生成しています。
あくまでシリアル処理です。


「なるほどね、シリアルな単純書き込み処理だと、アーキテクチャ的にAuroraのほうがオーバーヘッド大きそうだよね(ストレージレイヤが分離してるので)」で終わってしまうのはもったいないので、一般的?なワークロードでも、RDSの方がAuroraより速くなるケースはあるのか、調べてみることにしました。


試験の条件

RDS、Auroraともに同じマイバーバージョンが選択できるものを採用。


インスタンスタイプ/サイズも同じものを選択できるものを採用。せっかくなので、元記事と同じr5系で。

  • db.r5.large(2vCPU/16GiB Mem)
  • db.r5.xlarge(4vCPU/32GiB Mem)
  • db.r5.2xlarge(8vCPU/64GiB Mem)


その他細かい設定はこんな感じ。

  • RDSはMultiAZ、マスターノードはHammerDBが動くEC2とは別のAZ。
  • AuroraはWrite+Reader*1、WriterノードはHammerDBが動くEC2とは別のAZ(AZ-AのEC2 -> AZ-BまたはAZ-CのRDS & Aurora)。
    • 読み取りの負荷分散はしないけど(全部マスターノードへの接続)、待機系との連携負荷は含める。Auroraはシェアードディスクだけどレプリカへのキャッシュ転送がある。
    • 最近発表された「Multi-AZ DB Cluster」は、今回は試験してない。クラシック?なマルチAZ構成。
  • RDSのストレージはgp2:1000 GB(ベースラインIOPS=3000)、ストレージ自動拡張無効(スケールファクタ100では自動拡張を有効化しても発動しない)
  • パラメータグループ/クラスターパラメータグループはデフォルト。
  • ログのCloudWatch Logsへの転送は無効
  • 暗号化有効
  • 拡張モニタリング有効
  • Performance Insights有効
  • 自動バックアップ有効
    • 本番で自動バックアップ無効で運用することはないよね、ってことで、MySQLはbinlog出力する負荷が乗りますが、それも考慮に入れる。


負荷を発生させるのは、余力たっぷりのEC2上のHammerDB 4.0を使います。
HammerDBはver 4.2までリリースされていて、PostgreSQL系の性能向上改善が入っているのは知っていたけど、立て直すのがめんどくさかったので、もともと立ててあった4.0環境を使いました。


HammerDBの設定関係は、以下の通り。

  • pg_driver、mysql_driver=timedと接続先設定以外はデフォルト。*2
  • vu(同時実行数)パラメータは、ロギング等の設定共通、ケースに合わせてvu数のみ変更。
    • vu数は4,8,16,32,64,128,256,512の8パターンで実施(一部、256、512での試験を省略)

測定は複数回実施した上で平均値や中央値を使うべきですが、時間の都合上、全部1発取りです。
参考までに複数回試したケースもありますが、ほぼ同じスコアが出てました。


手順としては、HammerDBのBuildschemaでテストデータ生成した後、vuが小さい条件から断続的に実行してます。
データの再生成は、DB自体の変更、および、インスタンスタイプの変更時のみ実施しています。

TPC-Cベンチマークの測定結果について

HammerDBが弾き出す性能測定値であるNOPM、TPMの数値をのままを開示することは、色々と問題がありそうなので開示しません。
RDSのdb.r5.largeのTPMスコアを基準(1.0)とする相対値ベースとします。

0.xとなっている部分は、RDSのdb.r5.largeよりもTPMが低い値を叩き出した、ということです。

r5.largeの256多重、512多重については、それ以下の段階でスコアが打ち止めになったこともあり、試験を省略しています。

またPostgreSQLMySQL別々の相対評価とし、「PostgreSQLMySQL、どちらが速い!」みたいな話はしません。


PostgreSQL
f:id:atsuizo:20220408131357p:plain
PostgreSQL_benchmark

画像が小さいですが、以下のような結果になっています。

  • r5.2xlarge(グラフにおける緑と青)では、RDSの方が高いTPMスコアを計測したのは32多重以下。
  • r5.xlarge(グラフにおける黄色とグレー)では、RDSの方が高いTPMスコアを計測したのは64多重以下。
  • r5.large(グラフにおけるオレンジと水色)では、RDSの方が高いTPMスコアを計測したのは128多重以下。32より多重度を上げるとスコアが劣化する。実質、常にRDSの方が速い、という結果に。


画面キャプチャ残していないのですが、Performance Insightsで待機イベントの発生状況を眺めている限り、以下のような傾向が出ていました。

  • Aurora PostgreSQL
    • 「CPU」がvCPU数を超えても、「IO:XactSync」が伸びる間は性能も伸びる。頭打ちになると、「Lock:transactionid(トランザクション終了待機)」が激増し、性能が下がる。
    • 「IO:XactSync」については、パラメータで解消できる要素はなく、多重度を減らす、スケールアップする、コミット回数をへらす、といった対処が必要。
    • 「Lock:transactionid」もパラメータで解消できる要素はなく、多重度を減らす、トランザクションの時間を短くする(トランザクションを開きっぱなしのものをなくす)、ロック粒度を小さくする、などの対処が必要。

 

  • RDS PostgreSQL
    • CPU(CPU Time)がvCPU数を超えても、「LWLock:WALWrite(WALバッファの内容のディスクへの永続化待機)」が増え続ける。さらに「Lock:transactionid(トランザクション終了待機)」も増えていく。
    • wal_buffersを増やすことで緩和できる可能性がある(RDSのみ対応)


Aurora PostgreSQLについては、AWS公式で以下のような記事が公開されています。すばらしい!。
docs.aws.amazon.com

MySQL
f:id:atsuizo:20220408131431p:plain
MySQL_benchmark

画像が小さいですが、以下のような結果になっています。

  • r5.2xlarge(グラフにおける緑と青)では、RDSの方が高いTPMスコアを計測したケースはなし。
  • r5.xlarge(グラフにおける黄色とグレー)では、RDSの方が高いTPMスコアを計測したのは64多重以下。
  • r5.large(グラフにおけるオレンジと水色)では、RDSの方が高いTPMスコアを計測したのは128多重以下。32より多重度を上げるとスコアが劣化する。実質、常にRDSの方が速い、という結果に。


こちらも画面キャプチャ残していないのですが、Performance Insightsで待機イベントの発生状況を眺めている限り、以下のような傾向が出ていました。

  • Aurora MySQL
    • CPU(CPU Time)がvCPU数を超えても、wait/io/redo_log_flushが伸びる間は性能も伸びる。頭打ちになると性能が下がり始める。
  • RDS MySQL
    • CPUがvCPU数を超えても、wait/sync/cond/sql/MYSQL_BIN_LOG::COND_DONEが伸びるが性能が下がり始める。その後もこの待機イベントは伸びる。
    • 性能が下がり始めるあたりから、wait/io/table/sql/handlerの比率が上がる。

MySQLの待機イベントについては、AWS公式で以下のような記事が公開されています。すばらしい!
docs.aws.amazon.com

aws.amazon.com


所感

vCPU数に対して過剰な多重度での負荷がかかると、色々と「詰まり」を起こして性能が劣化する、という当然の結果がありつつ、スペックの高いインスタンスになるほど、Auroraの「高多重度に対する強さ、処理の詰まりにくさ」が見て取れます。
AuroraもRDSも、データ・レコードのロック寄りも先にログ周りの永続化(バッファからストレージに書き出すところ)とか、トランザクション管理などが詰まりやすい印象です。


Auroraはその部分が多重度を上げても詰まりにくいようにしてある反面、そもそもストレージをインスタンスに直接アタッチしているわけではないためか、多重度の低い単純処理ではその強みが活かせず、PostgreSQLにいたってはRDSの方が速いケースが稀に出てくるようです。


そして、32多重や64多重という、わりと小さめの多重度において、キッチリとAuroraが優位になっていますから、実際に使用される多くのOLTP系システム、あるいは、成長(利用者増)を想定しているシステムでは、Auroraにしておくほうが、急な負荷増などへ対応力という点でも安全、といっても良いかと思います。


元記事にあった

TLDR:最高のI / O速度を得るには、大きな(汎用)SSDディスクで通常のRDS Postgresを使用します。

という話ですが、このケースのように、低い多重度で大量の書き込みを行うような処理が中心になるシステムってなんだろう?DWH/データマートなど分析系かな、というところです。
元記事の読み取りのベンチマークも、1億件をまるごと「SELECT *」するテストのようですし。(AuroraでReadの速度が思ったほど出ていないのが意外でした)

こういった使い方だと、ベンチマーク/PoCやらないウチにRedshft等の別のDBを選んでしまいそう。



最後に

AWSの人も口酸っぱく言ってますが「とりあえず、実際に使うワークロードに近いものを作って計測しろ」という話ですね。

どこかで誰かがその人固有の目的のために計測した結果を鵜呑みにして「XXXの方が速いぜ!(キリッ」みたいなのヤメヨウネ、っていう。
今回の試験で使ったTPC-Cにしても、同じ条件で比較するためのモデルを作ったにすぎないものですから、あくまで参考情報です。


あと、これ。


サイジングで重要な諸元値は、同時接続数よりも「同時実行数」です。


最後にいつもの書籍紹介ですが、負荷試験といえばコレでしょう。DBだけでなくシステム全体における負荷試験についての実践的な内容がまとめられてますし、AWSベースですけどAWSだけじゃない基本的な考え方が押さえられてます。


2017年の発行か。月日が立つのが早い。

*1:AuroraはRDSに比べて、最高でMySQLで5倍、PostgreSQLで3倍速い、と謳われている。 Amazon Aurora(高性能マネージドリレーショナルデータベース)| AWS

*2:詳細条件とその意味を全部書くの辛いので、当ブログの別記事参考。 HammerDBをCLIで使うなど:まとめ、あるいは、目次の代わりに - なからなLife