2013年12月03日

[JPOUG Advent Calendar] Oracle on Hyper-V 2013

charade_oo4oと申します。昨年に引き続き、今年も「JPOUG Advent Calendar 2013」へ参加致します。今回もOracleとHyper-Vに関する話題です。
昨日はwrcsus4さんの「SQL*Plusで展開表示 - pr.sql from Tanel Poder's TPT scripts」でした。

 <2013年、OracleとHyper-V>

2013年のOracleとHyper-Vの動きを振り返ると、6月のクラウド分野での提携発表、9月のOracle OpenWorld 2013での基調講演、かなり進展がありました。
今ではMicrosoftのパブリッククラウドWindows Azureの仮想マシンギャラリーからOracle Databaseを選択可能です。

azure

 <Hyper-V、再検証環境>

昨年の「JPOUG Advent Calendar」にて、自分の投稿後の日程で公開されたblogを拝見して、1年越しに再検証したい点も出てきました。
1年経過した為、ホストOS、ゲストOS共にS/W環境を見直しました。

種別 OS bit DB
ゲストOS Windows Server 2012 Standard 64bit Oracle Database 11gR2 SEOne
ホストOS Windows 8.1 Enterprise 64bit

ターミナル・リリースの11.2.0.4にて2012がサポートされた為、ゲストOSを見直しました。まだ12cは検証途上です。
ホストOSは、サーバOS(2012R2)と同様の仮想化技術を使用するクライアントOS(8.1)を使用しました。クライアントOS向けのユーティリティを使用する為です。
H/W環境は変わらず、DISK I/OネックなHDDのNotePC(2コア4スレッド)です。

 <バルク処理、本当に有効?>

2012/12/10のakaganeerさんの「バルク・マージをやってみた。」を拝見して、バルク処理の有効性を確認したくなりました。ゲストOSのCPU割当数を検証する為の大量INSERTスクリプトにPL/SQLの単純ループ処理を使用していた為、バルク処理で速度改善出来ないかと思った次第です。
PL/SQL以外にSQLでのバルク処理(INSERT...SELECT文)も確認しました。2012/12/20のspitz2bassさんの「11gR2 再帰SQL」も試しましたが、WITH句ではsorts (memory)がレコード件数分発生してしまい性能が出なかった為、sorts (memory)が少なくて済んだ階層問い合わせ(CONNECT BY)を使用しました。
それぞれの処理概要は下記の通りです。

PL/SQL 単純ループ処理 PL/SQL バルク処理 SQL INSERT...SELECT文
FOR I IN 1..n
LOOP
  INSERT文;
END LOOP;
FORALL I IN 1..n
  INSERT文;
INSERT INTO "tablename" ( ... )
SELECT ... FROM DUAL
CONNECT BY LEVEL <= n;

まず、SQL*Plusで単独実行して、set timing onでの経過時間を比較しました。

単独実行
処理方法 処理時間
SQL INSERT...SELECT文 0:00:05.61
PL/SQL バルク処理 0:00:06.00
PL/SQL 単純ループ処理 0:00:14.76
sql_1

単独実行では、PL/SQL 単純ループ処理が最も遅く、PL/SQL バルク処理とSQL INSERT...SELECT文は2倍以上の処理速度でした。バルク処理は非常に有効だと思えます。

しかし、業務システムの本番環境では、複数の処理が同時実行される事も多いと思います。そこで、ゲストOS=2CPUのDISK I/OネックなHDD環境でINSERTスクリプトを多重実行しました。
ヒント「/*+ APPEND */」のダイレクト・パス・ロードでは表ロックがかかってしまい、多重実行ではなく連続的な単独実行となってしまうので、従来型・パス・ロードとしました。
PL/SQL バルク処理は若干遅かった為、SQL INSERT...SELECT文とPL/SQL 単純ループ処理を比較しました。

多重実行
処理方法 処理時間
SQL INSERT...SELECT文 0:01:29
PL/SQL 単純ループ処理 0:01:38
sql_n

単独実行では2倍以上の速度差が出ましたが、多重実行では10%程度しか差がありません。
単純ループ処理からバルク処理へ変更しても、DISK I/Oネックな環境ではあまり速度改善しない場合もあります。開発環境では効果有でも、本番環境ではさほど変わらず、そんな状況もありえるかも知れません。

StatspackのTop5待機イベントは下記の通りです。

SQL INSERT...SELECT文 2CPU(HDD): 処理時間=0:01:29
Event                 Waits Time
(s)
Avg
wait
(ms)
%Total
Call
Time
log buffer space 723 241 333 35.1
control file sequential read 1,196 88 74 12.9
log file parallel write 251 84 333 12.2
db file parallel write 1,455 71 48 10.3
log file sync 49 47 955 6.8

PL/SQL 単純ループ処理 2CPU(HDD): 処理時間=0:01:38
Event                 Waits Time
(s)
Avg
wait
(ms)
%Total
Call
Time
log buffer space 698 198 284 28.5
log file parallel write 445 83 187 12.0
CPU time
83
12.0
db file parallel write 1,377 68 49 9.7
db file sequential read 255 65 254 9.3

どちらの処理も「log buffer space」が1位です。昨年同様、log_bufferの拡大では速度改善せず、HDDがDISK I/Oネックとなっている様です。
PL/SQL 単純ループ処理では3位に「CPU time」がありますが、SQL INSERT...SELECT文では入っていません。タスクマネージャーでもCPUは低負荷でした。

 <SSD、DISK I/Oネック解消?>

2012/12/17のsh2ndさんの「Provisioned IOPSの検討 - JPOUG Advent Calendar 2012」を拝見して、SSDの採用でDISK I/Oネックを解消出来るのではないかと思いました。但し、大容量SSDの価格、フラッシュの書換寿命、懸念点を払拭出来ず未導入です。
そういえば、某ISV試験対策でVirtualBoxの仮想マシンを複数稼働させる為、NotePCのメモリを16GBへ拡張していました。最近は値上がりしている様ですが、購入当時はHDD並の価格でした。
メモリを8GB程度RAMDISK化して、そこにOracleのデータファイル一式を格納したVHDXファイルを置いて、SSD検証用に利用出来ないかと考えました。
サーバOS用のRAMDISKソフトが見つからなかった為、ホストOSはクライアントOS(8.1)としました。

まずはRAMDISK自体の性能確認で、ホストOSでのRAMDISK自体のドライブ、RAMDISKへ格納したVHDXファイルをホストOS自身でマウントしたドライブ、RAMDISKへ格納したVHDXファイルをゲストOS側から、それぞれCrystalDiskMarkで計測しました。

単独計測
ホストOS RAMDISK ホストOS VHDX ゲストOS VHDX
host_ram host_vhdx guest_vhdx

「ホストOS VHDX/ホストOS RAMDISK」の比率(VHDX化による性能劣化)は、最も良好なSequential Readでも0.8未満です。
「ゲストOS VHDX/ホストOS VHDX」の比率(Hyper-VのDISK処理による性能劣化)は、4K QD32以外では0.8-0.9なので、VHDX化による性能劣化の方が影響があります。
ホストOS VHDXでは、ベンチマーク実行時のCPU負荷高騰(冷却ファン回転数上昇)の影響で、最後に実行される4K QD32のスコアが低下していました。
ホストOS、ゲストOS共に、Fusion-io ioDrive2以上のスコアを叩き出しています。

次にOracleでの検証では、今回もPL/SQL 単純ループ処理のINSERTスクリプトを多重実行しました。ゲストOSのCPU割当数を1-4CPUへ変更して、HDD環境とSSD(RAMDISK)環境の双方での処理時間をグラフ化しました。
ゲストOS=2CPUのHDD環境でのStatspackのTop5待機イベントは上に記載済の為、2CPUのSSD環境のみ抜粋しました。1,3,4CPUでのStatspackは、昨年と似たような傾向だった為、割愛しました。

CPU割当数別処理時間
cpu_hdd_ssd

PL/SQL 単純ループ処理 2CPU(SSD): 処理時間=0:00:49
Event                 Waits Time
(s)
Avg
wait
(ms)
%Total
Call
Time
CPU time
89
38.9
resmgr:cpu quantum 247 55 223 24.0
buffer busy waits 12,390 19 2 8.4
db file parallel write 153 14 92 6.1
log file parallel write 950 12 13 5.3

昨年同様、DISK I/OネックなHDDでは、CPU割当数が多い程、処理時間が増えています。
対してSSDでは、CPU割当数が多い程、処理時間が減っています。CPUが使えれば使えるほど速度改善する様です。「CPU time」は2-4CPUで1位、1CPUで2位、「resmgr:cpu quantum」は1CPUで1位、2CPUで2位、3CPUで3位。CPUが高負荷な傾向です。

1CPUでの処理時間は、HDDでは0:01:32、SSDでは0:01:22。どちらの環境もCPUネックな為、DISK I/Oの影響が低く、ほぼ同等です。
2CPUでの「CPU time」は、HDDでは83秒、SSDでは89秒なので、ほぼ同等です。
HDD=>SSDでは、CPU負荷は変わらず、LGWRやDBWRでの待機が激減した為、結果的にDISK I/Oネック=>CPUネックとなった様ですが、処理時間自体は大幅に改善しています。

少し前に、HDDからFusion-io ioDrive2へリプレースしたOracleサーバを調査した事があるのですが、そこでも慢性的なDISK I/Oネックが完全解消していました。
Fusion-ioは数年前まで米国メーカーを中心に採用されていましたが、最近は国内メーカーでも採用が進んでいます。2012年末には富士通へioDrive2のOEMを開始しており、2013年には日立から「Fusion- ioを用いたサーバ高速化モデル」が発表されています。
近い将来、SATA Express、SCSI Express、NVM Express等の規格で、PCIeフラッシュは更に身近な技術となるかも知れません。

ExadataやOracle Database Appliance等のEngineered Systemsに限らず、DB処理能力不足をSSD等のH/Wの力で解決出来る、そんな時代が来ている様です。

 <ホスト/ゲスト、どちらが大事?>

2012/12/06のGo Watanabeさんの「Oracle VM Server のファイルコピーを考える」を拝見して、Hyper-Vでもホスト OSとゲストOSでのDISK I/O同時負荷の影響を確認したくなりました。
Hyper-VもXen同様、ゲストOS(子パーティション)でのDISK I/Oや外部NETWORK I/Oは、ホストOS(親パーティション)経由で担当しています。
そこで、DISK I/O性能に余裕があるRAMDISK環境で、ホストOSとゲストOSの双方でCrystalDiskMarkを同時に計測しました。片方のみで計測が実行されてしまうとそちらのスコアが上がってしまうので、計測ボタン毎に何度か再試行しています。

同時計測
ホストOS RAMDISK ゲストOS VHDX
para_host para_guest

ホストOS、ゲストOS共、Sequential Read Writeは単独計測と比べて半減しています。2つ同時なので、性能も半分になった様です。
しかし、同時に32命令実行する4K QD32は、ホストOS側は殆ど性能劣化していませんが、ゲストOS側は1/4以下まで落ち込んでいます。単独計測での1命令実行の4K(QD1)よりも低いスコアです。Small Random Read Writeが多重実行された場合、ホストOS側のDISK I/Oを優先している様です。

ホストOSとゲストOSの処理の優先度は、ある程度は制御可能です。
タスクマネージャー=>詳細=>優先度の設定(リアルタイム,高,通常以上,通常,通常以下,低)、又はDOSコマンドのSTARTのオプション(REALTIME,HIGH,ABOVENORMAL,NORMAL,BELOWNORMAL,LOW)で、プロセスの優先度を変更可能です。
ゲストOS側での優先度の設定変更は殆ど計測結果に影響しなかったのですが、ホストOS側でCrystalDiskMarkの優先度を変更するとゲストOS側の計測結果がかなり変わりました。
ホストOS:HIGHへ設定すると、ゲストOS側の4K QD32は1桁台まで落ち込みました。逆に、ホストOS:LOWへ設定すると、ゲストOS側の4K QD32は100以上となりました。
CPUのスケジューラ設定で、ホストOSとゲストOSの処理の優先度をある程度見直し出来ましたが、ゲストOS側がホストOS側の計測結果を上回る事は無く、ホストOS側のDISK I/O優先の傾向自体は変わりませんでした。

OS設定のプロセッサのスケジュール「プログラム」「バックグラウンドサービス」も影響する様ですが、バラつきが大きく計測毎に傾向が変わってしまいました。
クライアントOS(8.1)では「プログラム」が初期設定、サーバOS(2012R2)では「バックグラウンドサービス」が初期設定です。

ゲストOS側でDISK I/O性能が必要な場合、ホストOS側からSmall Random Read Writeが発生しない様にする必要がありそうです。ホストOS側からの大量なSmall Fileのバックアップは要注意です。

 <サイジング、そんなに沢山必要ですか?>

最近のx86サーバの売れ筋は、性能と価格のバランスが良好な2WAYサーバです。ExadataやOracle Database ApplianceでもE5-2600シリーズを2CPU搭載するモデルがあります。
また、最近のx86サーバではNUMA(Non-Uniform Memory Access)を採用しています。CPUにコントローラを内蔵して、メモリやPCIeカードと直接アクセスしています。NUMAには長所もありますが短所もあります。

 【NUMAの長所】
・同一NUMAノード内でのメモリやPCIeカードへのアクセスが速い。
・OS:2012やHyper-VはNUMAに対応。

 【NUMAの短所】
・NUMAノードを跨るリモートメモリやPCIeカードへのアクセスは遅い。
・片方のCPUが省電力機能でダウンクロックしている場合は更に遅い。
・Oracle Databaseは11gR2以降NUMA最適化機能を無効化。
・NUMAノードのメモリ搭載量を超える様な巨大なプロセス(DBのキャッシュ等)では、マシン全体では空きメモリがある場合でも、NUMAノード間でのリモートメモリアクセスをせずにスワップアウトする事がある(Swap Insanity)。

一昔前の32bitOSの頃は、搭載メモリの半分以上を1プロセスに割り当てる事も少なく、GbEやRAIDカード等のI/Fも低速でした。
しかし最近は大容量メモリ搭載が現実的で、高速なI/Fも増えています。その為、NUMAの短所が顕在化する危険性も増えています。
MySQLやFusion-ioの事例でも、NUMAの弊害を聞いた事があります。

回避策として、CPUを1つのみ搭載する(複数搭載しない)という方法があります。CPUが1つならNUMAノードも1つです。
最近はマルチコア化が進んでいるので、1CPUでも性能面の不安は低減しています。NECの垂直統合型システム「Data Platform for Oracle Database」でも1CPUモデルがあります。

CPUを複数搭載する場合、巨大な単独インスタンスではなく複数インスタンスに分割して、1プロセスのメモリ割当をNUMAノードのメモリ搭載量以下に抑える回避策もあります。
サイジングの参考にOracle Database Applianceのオンラインドキュメントを参照した所、最大規模のSGA割当量でもNUMAノードのメモリ搭載量以下に抑えていました(最大SGA:NUMAノードメモリの割合は、V1では48GB:48GB、X3-2では64GB:128GB)。
BIOS/UEFI設定やOS/Hypervisor設定でNUMAを無効化する回避策もありますが、最近のサーバ自体がNUMA推奨である事が多く、NUMAノード内より7-8割程遅いリモートメモリアクセスを基準とするのが良いか微妙です。
F1のタイヤ戦略に例えるなら、プライムで長いスティントをゆっくり走るか、オプションで短いスティントに分けて飛ばすかの違いです。

H/Wのサイジングで余裕を持って2CPUとするとNUMAの弊害に陥る危険性、HugePage非採用のLinuxで余裕を持ったメモリサイジングをするとメモリスワップに陥る危険性にも似ているかも知れません。

 <まとめ>

・DISK I/O負荷が高い環境では、バルク処理での改善効果が低い場合有。
・SSD等のH/Wの力でDB処理能力不足を解決する方法も有効。
・Hyper-VのゲストOSのDISK I/Oは、ホストOSでのSmall Random Read Writeの影響を受け易い。
・CPUやメモリのサイジングは程々に。多過ぎてもトラブルの原因となりえる。

明日はKeiji Odaさんです。

posted by charade at 00:00| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック