データベース・サーバの「マルチプログラミング・レベル」は、同時にアクティブにできるタスクの最大数です。-gn サーバ・オプションによって制御されます。アクティブ・タスクは、データベース・サーバにおいて 1 つのスレッド (またはファイバ) によって現在実行されているタスクを指します。アクティブ・タスクは、アクセス・プランの演算子を実行したり、その他の実質的な処理を行ったりします。ただし、(I/O 操作やロー・ロックなどのために) リソースを待機することもあります。未スケジュールのタスクは、実行の準備が整っているものの、利用可能なスレッドやファイバを待機しているタスクを指します。同時に実行できるアクティブ・タスクの数は、データベース・サーバのスレッドの数と、コンピュータに搭載されている論理プロセッサの数によって異なります。
マルチプログラミング・レベルは、サーバの実行中は一定に維持され、サーバ上のすべてのデータベースに適用されます。アクティブ・タスクのデフォルト数は、ネットワーク・データベース・サーバおよびパーソナル・データベース・サーバでは 20 ですが、Windows Mobile のデフォルトは 3 です。
マルチプログラミング・レベルをどのタイミングで上げたり下げたりするかを決定するのは、難しいことがあります。たとえば、データベース・アプリケーションが Java ストアド・プロシージャを利用する場合や、クエリ内並列処理が有効になっている場合、これらの要求を処理するために追加で作成されたサーバ・タスクは、マルチプログラミングの制限を超えると、他の要求が完了するまで実行を待機することになります。このような状況では、マルチプログラミング・レベルを上げることが適切です。多くの場合、マルチプログラミング・レベルを上げると、データベース・サーバの全体的なスループットも相応して向上します。これは、マルチプログラミング・レベルを上げることによって同時に実行できるタスク (要求) の数が増えるためです。ただし、マルチプログラミング・レベルを上げるときに検討が必要なトレードオフがあります。これには次のようなものがあります。
競合の増加 同時に実行するタスクの数を増加すると、アクティブな要求間で競合が発生する可能性が高まることがあります。競合はリソースに関連するもので、スキーマ・ロックやロー・ロック、データベース・サーバ内部のデータ構造や同期プリミティブなどが挙げられます。このような状況では、サーバのスループットが実際に低下することがあります。
サーバのオーバヘッドの増加 各アクティブ・タスクは、スレッドの割り付けと管理を要求します (Windows と Linux の場合は、軽量スレッドがファイバを呼び出します)。スケジュールを制御するために追加の管理構造も必要です。さらに、各アクティブ・タスクは、実行スタックに対するアドレス領域の事前割り付けを要求します。スタック・サイズはプラットフォームによって異なりますが、32 ビットのプラットフォームで約 1 MB、64 ビットのプラットフォームではより大きなサイズが必要です。Windows システムでは、スタック領域の割り付けはサーバ・プロセスのアドレス領域に影響を及ぼします。ただし、スタック・メモリは要求に応じて割り付けられます。UNIX プラットフォームの場合 (Linux を含みます)、スタックの退避メモリが即座に割り付けられます。したがって、マルチプログラミング・レベルを上げると、サーバのメモリ・フットプリントが増加します。また、利用できるアドレス領域が少なくなるため、キャッシュで利用できるメモリ量が減少します。
スラッシング データベース・サーバは、個々の要求に対する処理を実行するためではなく、実行のオーバヘッドを管理するためだけに、多量のリソースを使用する状態に陥ることがあります。この状態は一般的に「スラッシング」と呼ばれています。スラッシングが発生するのは、データベース・キャッシュ内の領域に対して競合するアクティブな要求の数があまりに多く、これらの要求のセットが使用するデータベース・ページのワーキング・セットを保てるほどキャッシュが大きくない場合などです。結果として、オペレーティング・システムで発生する場合と同様に、ページの横取りが発生することがあります。
クエリ処理への影響 データベース・サーバは、同時に処理可能なメモリを大量に消費する要求の最大数を選択します。データベース・サーバのマルチプログラミング・レベルを上げても、メモリが利用可能になるまで、要求が待機状態になる場合があります。メモリ・ガバナーを参照してください。
データ構造のメモリ データベース・サーバは、リソースを使用して文を解析したり、最適化したりします。複雑な文やキャッシュ・サイズが小さい場合、サーバ・データ構造に使用されるメモリのサイズが利用可能な上限を超えてしまう場合があります。各タスクのサーバ・データ構造に使用するメモリ量は、メモリ・ガバナーによって制限されます。各タスクには、次の制限があります。
(3/4 maximum cache size) / (number of currently active tasks) |
制限を超えると、文にはエラーが発生します。
同時に実行するタスクの数を減らしてデータベース・サーバのマルチプログラミング・レベルを下げると、一般に、サーバのスループットは低下します。ただし、マルチプログラミング・レベルを下げることで、個々の要求の応答時間は短縮されることがあります。これは、リソースに対して競合する要求の数が少なくなり、ロック競合の確率が低下するためです。
SQL Anywhere では、スレッド (ファイバ) は協調的な方法でタスクを実行します。あるタスクが完了すると、スレッド (ファイバ) は、実行を待機している次のタスクを選択できます。ただし、ロー・ロックを待機している場合など、タスクがブロックされていると、スレッド (ファイバ) もブロックされます。
マルチプログラミング・レベルを下げすぎると、「スレッド・デッドロック」が発生することがあります。データベース・サーバに n スレッド (ファイバ) を設定した場合を考えてみます。n-1 の数のスレッドがブロックされているときに最後のスレッドをブロックしようとすると、スレッド・デッドロックが発生します。データベース・サーバのカーネルは、最後のスレッドをブロックすることを許可できません。ブロックすることによって、すべてのスレッドがブロックされ、サーバがハングするためです。ブロックを許可する代わりに、データベース・サーバは、最後のスレッドをブロックしようとしたタスクを終了します。このとき、SQLSTATE 値には 40W06 が設定されます。
マルチプログラミング・レベルが負荷に対して適切なレベルになっていて、スレッド・デッドロックが発生する場合は、アプリケーション設計に問題があることが考えられます。結果として競合が発生し、延いてはスケーラビリティが低下します。例として、データベースに新しいデータを挿入するときにすべてのアプリケーションが変更を加える必要のあるテーブルについて考えてみます。この方法は、プライマリ・キーを生成するスキームの一部として、よく使用されます。このようなテーブルでは、結果として、アプリケーションの挿入トランザクションのすべてが事実上直列化される状況になります。共有テーブルが直列化されることに起因して、サーバがサービスを提供する速度よりも挿入トランザクション速度の方が速くなると、通常、スレッド・デッドロックが発生します。
アプリケーションの負荷を測定し、サーバ・スループットと要求の応答時間に対する、サーバのマルチプログラミング・レベルの効果を分析することをおすすめします。プロパティ機能と同様に、さまざまなパフォーマンス・カウンタを利用できます。Windows 環境でアプリケーション・テスト時にデータベース・サーバ動作を分析するには、Windows パフォーマンス モニタが役立ちます。この分析には、アクティブな要求や未スケジュールの要求に関連のあるパフォーマンス・カウンタが重要です。
アクティブな要求の数が、-gn データベース・サーバ・オプションの値よりも常に小さくなる場合は、マルチプログラミング・レベルを下げることを検討します。ただし、サーバの実行キューに対してタスクを追加するクエリ内並列処理の効果を考慮に入れる必要があります。クエリ内並列処理の効果が不十分である場合は、全体的なシステム・スループットを低下させることなく、安全に、マルチプログラミング・レベルを下げることができます。要求の総数 (アクティブな要求 + 未スケジュールの要求) が -gn データベース・サーバ・オプションの値よりも大きくなることが多い場合は、上に概要を示したトレードオフを前提として、マルチプログラミング・レベルを上げることができます。パフォーマンス・モニタは、UNIX または Linux プラットフォームでは使用できないことに注意してください。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |