皆さん、明けましておめでとうございます。今年も素敵な一年になりますようお祈り申し上げます。
今回は、苦労されている方も多い、パラレル実行と同時実行のリソース管理について説明しようと思います。後半に、これが簡単に利用できるようになっているOracle Autonomous Databaseについても説明していますので、参考にしてください。
1. パラレル実行の同時実行管理
パラレル実行は、第20回で説明したように、処理時間を大幅に短縮することができますが、同時実行するとある時点でリソース制限に行きあたるので、SQL文ごとのパラレル度(DOP)と同時実行するSQL数との間でバランスをとることが大事になります。自動DOPフレームワーク(自動DOPとパラレル・ステートメント・キューイング)を使用することで、ユーザーの介在なしにパラレル処理の使用状況を総体的に(バランスよく)制御することが可能です(自動DOPは、Oracle12cからDBMS_RESOURCE_MANAGER.CALIBRATE_IOプロシージャを実行しない場合でも、デフォルト値を使用して動作するようになりました)。ただし、優先順位の高いSQLなどもあるので、第40回で説明したDatabase Resource Managerと一緒に制御する方がより効果的です。これまでは、自動DOPフレームワークとリソース管理の使い方までは説明していなかったので、以下についてのガイドをまとめてみました。
- パラレル実行(PX)サーバー・プロセス数の管理
- パラレル・ステートメント・キューイング(PSQ)を使用したパラレル処理の管理
- Database Resource Manager(DBRM)を使用したパラレル処理の管理
(1)PXサーバー・プロセス数の管理
まずは、パラレル実行に使用されるPXサーバー・プロセス数の決定について説明します。
PXサーバー・プロセスは、プロセスのプール(PARALLEL_MAX_SERVERS初期化パラメータで最大数を設定)からパラレル操作に割り当てます。デフォルトでは、以下のように設定されるので、基本はこれで問題ありません(CPU時間の割合が多いSQL文のときには、CPU使用率の確認を行うようにしてください)。
PARALLEL_MAX_SERVERS = 5 × <concurrent_parallel_users> × <デフォルトDOP>
デフォルトDOPは、CPU_COUNT×PARALLEL_THREADS_PER_CPU×起動インスタンス数(RAC環境のみ)になり、自動DOPではデフォルト最大DOPとして使用されます(PARALLEL_THREADS_PER_CPU初期化パラメータのデフォルトは、Oracle18cから1になっていますが、インテルのHyperThreading機能が無効のときは2の方が最適です)。
concurrent_parallel_usersの値は、初期化パラメータMEMORY_TARGET、SGA_TARGET、PGA_AGGREGATE_TARGETによって以下のようになります(参考までに、デフォルトDOPでの同時実行数も載せておきました)。
| MEMORY_TARGET/SGA_TARGET | PGA_AGGREGATE_TARGET | concurrent_parallel_users | デフォルトDOPの同時実行数 |
| 設定 | – | 4 | 10(5*4/2) |
| 未設定 | 設定 | 2 | 5(5*2/2) |
| 未設定 | 未設定 | 1 | 2(5*1/2) |
パラレルSQL文は、プール内のプロセスがすべて割り当てられると、シリアル(非パラレル)実行またはDOPがダウングレードされてパフォーマンスが低下します。そのため、自動DOPの場合は、もう1つの制限として、PSQの前に使用可能なPXサーバー・プロセス数(PARALLEL_SERVERS_TARGET初期化パラメータ)が使用されます。デフォルトは、PARALLEL_MAX_SERVERSの40%で、キューを迂回するパラレルSQL文のために、いくらかのバッファが確保されています(存在しない場合は増やしてください)。なお、PSQをアクティブ化しても、シリアルSQL文はすべて即時実行されます。PARALLEL_SERVERS_TARGETが考慮されるのは、PARALLEL_DEGREE_POLICY初期化パラメータをAUTOまたはADAPTIVEに設定している場合のみです(ADAPTIVEでは、第33回で説明したパフォーマンス・フィードバックも動作しますが、Oracle18cからOPTIMIZER_ADAPTIVE_STATISTICS初期化パラメータがFLASEでも動作するようになりました)。
(2)PSQを使用したパラレル処理の管理
次に、同時実行を制御するPSQの調整方法について説明します。
同時実行の制御は、第20回でPARALLEL_ADAPTIVE_MULTI_USER初期化パラメータも可能ですと説明しましたが、Oracle12cR2からデフォルトはFALSEになり非推奨となりましたので、PSQを使用してください。
自動DOPフレームワークでは、PSQを使用してPXリソースが使用可能になってから実行させるので、調整ポイントはSQL文が長時間キューイングされていないかになります(以下の手順で確認するようにしてください)。
- SQL文がキューで待機していないかを待機イベント’resmgr: pq queued’(11.2.0.2から)で確認する。
- キューイングされているSQL文は、以下のSQL(V$SQL_MONITOR/GV$SQL_MONITORビュー)またはOracle Enterprise ManagerのSQLモニター画面を使用して特定する。
SQL> SELECT sql_id, sql_text, rm_consumer_group FROM V$SQL_MONITOR WHERE status='QUEUED';
SQL文がPSQにより遅くなっている場合は、以下の手順で検討を行ってください。
- SQLが最適に実行しているか(できるだけSQLチューニングを行い最適な実行計画にする)
- パラレルになる最小実行時間(PRALLEL_MIN_TIME_THRESHOLD)を大きくできないか(パラレルSQL文を減らす)
- 最大DOP(PARALLEL_DEGREE_LIMIT)を下げられないか(またはDBRMで複数レベルの最大DOPにできないか)
- PARALLEL_SERVERS_TARGETを大きくできないか(リソースに余裕がある場合)
- ワークロードに対してシステムのサイズが小さすぎないか
また、キューイングさせたくないパラレルSQL文は、NO_STATEMENT_QUEUINGヒントを使用するか、第40回で説明したPARALLEL_STATEMENT_CRITICALパラメータがBYPASS_QUEUEに設定しているユーザーで実行すると、PSQをバイパスしてすぐに実行できます。
(3)DBRMを使用したパラレル処理の管理
次に、PSQの優先順位が設定できるDBRMについて説明します。
第40回の「パラレル・ステートメント・キューイングのリソース管理について」で説明したように、DBRMと一緒に使用してリソース・コンシューマ・グループ(コンシューマ・グループ)ごとにPSQのキューを管理することで、以下のことができるようになります。
- 個々のSQL文やコンシューマ・グループ全体で使用できるPXサーバー数を制御する
- 優先順位の高いコンシューマ・グループに、より多くのPXリソースを割り当てる
- ユーザー毎に異なるキューを割り当て、優先順位の高い要求が低い要求の後にキューイングさせない
そのため、同時実行環境でパラレル実行する場合は、DBRMで複数のコンシューマ・グループを使用することを強くお勧めします(この後のAutonomous Databaseの設定を参考にすると良いと思います)。
また、これから使用する機会が多い(Autonomous Databaseでも使用されている)PDBのリソース管理についても説明しておきます。
PDB(プラガブル・データベース)について
ご存知ない方のために、ここでマルチテナント・アーキティクチャ(MTA)のPDBについて簡単に説明します。
MTAは、データベースのマルチテナント(1つのシステムに複数のサービスが同居している環境)を効果的に実現するために、Oracle12cから一つのインスタンス(メモリー、バックグランド・プロセス)上で、複数の仮想的なデータベースを稼働するようにした機能です。インスタンスが動作するマルチテナント・コンテナ・データベース(CDB)と、それに内包される一つ以上のPDBで構成され、これまでのデータベース(非CDBと呼ぶ)からも変更せずに使用できます。このMTAにより、これまでのデータベース統合の課題(スキーマ分割はリソースを分割できない、複数データベースや仮想マシンは個々に必要なリソースや管理コストなどが増える)を以下のように解決し、ITコストの削減に貢献することが可能になります。
- 高密度の統合
CDB上のCPUやインスタンスを共有することで、リソースを有効に活用でき(PDB間の動的なリソース管理もでき)、高いパフォーマンスと集約密度(1サーバー当たりのデータベース数)の向上を実現します。 - 多数のデータベースの一元管理
アップグレードやパッチ適応、バックアップ/リカバリ、インスタンス・チューニングなどを、CDBレベルで行うことで、管理コストを削減します(CDB全体のバックアップからPDB単位でのリカバリ、他のPDBに影響させずにバッファ・キャッシュのフラッシュなども可能です)。 - 迅速なプロビジョニング
様々なプロビジョニング(CDB内に新しいPDBを作成する、既存のPDBをクローンする、既存の非CDBをPDBとしてCDBに移行、切断したPDBを異なるCDBに接続するなど)を簡単および迅速にできることで、いろいろな場面で効果的に使用することが可能になります。
PDBリソース管理は、以下のように、2つのレベルのリソース・プランをsharesパラメータ(共有値:リソースの割合)で作成して行います(DBRMを使用しないと、初期化パラメータだけで制御することになります)。
- CDBリソース・プラン
CDBリソース・プランを作成し、優先度に従ってPDBごとにリソースを配分します(作成しないでPDBリソース・プランが作成されると、付属のDEFAULT_CDB_PLANが使用されます)。sharesは、PDBに対するソフト・リミットになるので、CPUリソースの上限値はutilization_limitパラメータ(またはCPU_COUNT初期化パラメータ)、PXサーバー数の上限値はparallel_server_limitパラメータ(またはPARALLEL_SERVERS_TARGET初期化パラメータ)で制御します(Oracle12cR2からメモリー関連やI/O関連も初期化パラメータで指定できます)。 - PDBリソース・プラン
PDBに接続してPDBリソース・プランを作成し、PDB内のコンシューマ・グループごとにリソースを配分します。これまでの非CDBリソース・プランと同じように行いますが、いくつかの制限(ディレクティブのレベル数、コンシューマ・グループ数、サブプランを設定できない)があります。リソース割り当ては、マルチレベル管理ディレクティブ(mgmt_p2からmgmt_p8)は使用できないので、mgmt_p1またはOracle12cからのsharesを使用します(推奨はsharesです)。
以下に、設定している例を載せておきます(CPUリソースはCPU_COUNTを使用しています)。このCDBリソース・プランは、DEFAULT_CDB_PLANと同じですが、参考のために載せておきました。
DECLARE
l_plan VARCHAR2(30) := ‘test_cdb_plan’;
BEGIN
DBMS_RESOURCE_MANAGER.clear_pending_area;
DBMS_RESOURCE_MANAGER.create_pending_area;
— CDBのプラン作成
DBMS_RESOURCE_MANAGER.create_cdb_plan(plan=>l_plan,
comment=>’test CDB resource plan’);
— PDB(pdb1)にリソース配分
DBMS_RESOURCE_MANAGER.create_cdb_plan_directive(plan=>l_plan,
pluggable_database=>’pdb1′,
shares=>1);
…<他のPDBは省略>…
DBMS_RESOURCE_MANAGER.validate_pending_area;
DBMS_RESOURCE_MANAGER.submit_pending_area;
END;
/
— PDBリソース・プラン作成
ALTER SESSION SET CONTAINER = pdb1; — PDB(pdb1)に接続
ALTER SYSTEM SET CPU_COUNT = 10 SCOPE = BOTH;
BEGIN
DBMS_RESOURCE_MANAGER.clear_pending_area;
DBMS_RESOURCE_MANAGER.create_pending_area;
— PDBのプラン作成
DBMS_RESOURCE_MANAGER.create_plan(plan=>’pdb1_plan’, comment => ‘pdb1 Plan’);
— コンシューマ・グループの作成とサービスのマッピング
DBMS_RESOURCE_MANAGER.create_consumer_group(consumer_group=>’high’,
comment=>’high priority’);
DBMS_RESOURCE_MANAGER.set_consumer_group_mapping
(attribute=>DBMS_RESOURCE_MANAGER.SERVICE_NAME,
value=>’pdb1_high’, consumer_group=>’high’);
— プラン・ディレクティブをコンシューマ・グループに割り当てて優先順位やリソース制限を定義する
DBMS_RESOURCE_MANAGER.create_plan_directive(plan=>’pdb1_plan’,
group_or_subplan=>’high’,
comment=>’High Priority – level 1′,
shares=>4,
parallel_server_limit=>50,
parallel_degree_limit_p1=>10);
…<他のコンシューマ・グループは省略>…
DBMS_RESOURCE_MANAGER.validate_pending_area;
DBMS_RESOURCE_MANAGER.submit_pending_area;
END;
/
2. Oracle Autonomous Database
最後に、パラレル実行と同時実行が簡単に利用できるAutonomous Database(ADW:Autonomous Data WarehouseとATP:Autonomous Transaction Processing)について説明します。
同時実行する環境では、様々なことを考えて設定する必要があり、大変と思っている方も多いのではないでしょうか。そのため、何もしなくても効果的に実行できるように、事前設定されているのがAutonomous Databaseです(パラレルDMLもデフォルトで有効になっています)。また、管理を簡単にするために、それぞれをPDBとして作成されています。ここでは、参考のために、どのように設定されているかを簡単に説明します(非常によく考えられているので、参考になると思います)。
Autonomous Databaseでは、以下のようなコンシューマ・グループ(サービス)で事前定義されているので、どのサービスを使用するかを検討するだけになります(TPとTPURGENTはATPのみです)。そのため、性能を改善するには、OCPU(Oracle Compute Units:CPUコア)の数を増やすだけになります(OCPU数に比例して、メモリーサイズ、I/O帯域幅が拡張されるようになっています)。
| サービス (コンシューマ・グループ) | SHARES | パラレル制御 | PX Degree Limit | PX Server Limit | 同時実行セッション数 |
| HIGH | 4 | 自動DOP | CPU_COUNT | 50% | 3(MEDIUMが存在しない場合) |
| MEDIUM | 2 | 自動DOP | 4 | 84% | 1.25×OCPU |
| LOW | 1 | シリアル | 1 | – | 100×OCPU |
| TP | 8 | シリアル | 1 | – | 100×OCPU |
| TPURGENT | 12 | 手動 | – | – | 100×OCPU |
| OTHER_GROUP | 1 | シリアル | 1 | – | 100×OCPU |
パラレル実行する場合は、HIGHとMEDIUMの2つのグループで最大DOPを使い分けることが可能です。初期化パラメータPARALLEL_MAX_SERVERSとPARALLEL_SERVERS_LIMITは、どちらもデフォルトではなく(3×4×<デフォルトDOP>)になっているので、HIGHの同時実行数は、MEDIUMの問合せが存在しない場合にpx_server_limitが50%から3となります(MEDIUMの問合せが存在する場合は、px_server_limitが84%になっているので、少なくても1つのSQL文は実行できます)。ATP用のTPURGENTは、最も優先度の高い(緊急度の高い)処理として、手動DOP(ヒントや表レベル)を使用できるようになっています。OTHER_GROUPは、デフォルト・コンシューマ・グループ(HIGH~TPURGENT)を使用しないときのグループになります。
sharesの割合は、2019/04新機能からCS_RESOURCE_MANAGER.update_plan_directiveプロシージャを使用して変更できるようになっています(OCIコンソールの「サービス・コンソール」→「Administration」→「Set Resource Management Rules」からも行えます)。例えば、以下のように変更(HIGHが6、MEDIUMが2、LOWが1)を行います。sharesは、ソフト・リミットになるので、高負荷のときに保証される割合になります。
BEGIN CS_RESOURCE_MANAGER.update_plan_directive(consumer_group => 'HIGH', shares => 6); CS_RESOURCE_MANAGER.update_plan_directive(consumer_group => 'MEDIUM', shares => 2); CS_RESOURCE_MANAGER.update_plan_directive(consumer_group => 'LOW', shares => 1); END; /
コンシューマ・グループの設定内容は、以下のSQL(DBA_RSRC_PLAN_DIRECTIVESビュー)で、リソース・プラン・ディレクティブから確認できます(’DWCS_PLAN’がADW、’OLTP_PLAN’がATP、そしてsharesがmgmt_p1になります)。
SQL> SELECT plan, group_or_subplan name, mgmt_p1 shares, parallel_server_limit, parallel_degree_limit_p1
2 FROM dba_rsrc_plan_directives
3 WHERE plan IN ('DWCS_PLAN', 'OLTP_PLAN')
4 ORDER BY 1,3 DESC ;
PLAN NAME SHARES PARALLEL_SERVER_LIMIT PARALLEL_DEGREE_LIMIT_P1
---------- ------------ ---------- --------------------- ------------------------
DWCS_PLAN HIGH 6 50 10
DWCS_PLAN MEDIUM 2 84 4
DWCS_PLAN LOW 1 1
DWCS_PLAN OTHER_GROUPS 1 1
このようにクラウド環境でもあるので、非常に簡単に管理ができるようになっています(慣れた管理者には、少し不自由さを感じるかもしれませんが、管理するシステムを削減できると思えば嬉しいことだと思います)。
Autonomous Databaseに興味を持たれた方は、「Oracle Database編 – Autonomous Database (ADB)を使ってみよう」にハンズオン情報がありますので、使用してみてください。
3. おわりに
今回は、パラレル実行とリソース管理について説明しましたが、少しは参考になりましたでしょうか。これからも頑張りますので、今年もよろしくお願いします。
それでは、次回まで、ごきげんよう。
