この章では、SQL ServerがCPUリソース(コンピュータに搭載されたSQL Serverが利用可能なプロセッサ群)を効率的に使用するために、どのような工夫をしているかを紹介します。さらに、実際のCPUリソースの割り振りに関する具体的な動作について見ていきます。
皆さんは、SQL Serverが内部的にOSのような機能を持っているという話を聞いたことがありますか?いくつかの書籍やWebサイトで語られているように、SQL Serverには「OSのような機能群」が内包されています。その機能群の中から、まずCPUリソースの使用方法という切り口で、歴史的な背景、具体的な動作、そして監視方法(モニタリング)までを紹介します。
1.1 マルチスレッドプログラミング
プログラム内の処理の実行単位、あるいはCPUの利用単位を表す言葉としてスレッドがあります。一連の処理を単一スレッドのみでシリアルに処理するプログラミング手法をシングルスレッドプログラミングと呼びます。これに対して、同一アドレス空間のメモリを共有しながら、ある処理を並列で実行する手法はマルチスレッドプログラミングと呼ばれます。複数のCPUを搭載するコンピュータでそれぞれの手法を採用 したプログラムを実行すると、一般的にはマルチスレッドのほうが恩恵を受けやすくなります(図1.1)。
もともとSQL Serverはサイベース社の製品「Sybase SQL Server」として開発されましたが、かつてデータベース製品を持っていなかったマイクロソフトが、自社オペレーティングシステムでの独占使用権を獲得したところから協業が始まりました(図1.2)。当時マイクロソフトは自社のサーバー用OSとして、現在のWindows ServerのもととなったWindows NTのごく初期のバージョンを開発・販売していました。
最初のWindows NT版SQL Serverが「Microsoft SQL Server」としてリリースされた頃(1990年代初頭)、商用環境で使用されるOSの主流の1つであったUNIXオペレーティングシステム[※1]にはマルチタスク処理には対応しているものの、マルチスレッド処理には対応していないものが数多く存在していました。
マルチタスク処理とは、異なるアプリケーション(あるいはプロセス)の処理を異なるCPUに割り当てることによって、複数のアプリケーションの処理を効率的に進めることができる仕組みです。マルチスレッド処理とは、さらに並列処理の効率化を進めるために、1つのアプリケーション内の操作を複数のスレッドに分割し、それぞれのスレッドに対して異なるCPUを割り当て、各スレッドを並列で処理することによって処理効率を高める仕組みです。UNIX上でのSybase SQL Serverは純粋な意味でのマルチスレッドで動作することはできませんでした。
しかしWindows NTでは、マルチスレッドのスケジュール管理機能が実装されていました。Microsoft SQL Serverはその機能を活用し、マルチスレッドで動作するように設計されていて、これは当時としては画期的な手法でした。それ以降、SQL Serverが小中規模システム向けのデータベースとして利用されていた期間は、何の問題もなく機能していました。しかし、SQL Server 6.5がリリースされて、徐々に大規模なシステムでの採用が進み始めた頃から、スケーラビリティの面での不安が指摘されるようになりました[※2]。その理由を、Windows OSのスケジューラの動作を含めて考えてみましょう。
[※1]現在広く利用されているLinuxはUNIXの派生の1つと言えます。
[※2]この時点でSQL Serverに求められたスケーラビリティとは、従来よりも大きなサイズのデータベースを問題なく管理する能力や、より多くのクライアントからのリクエストを効率的に処理する能力でした。
1.1.1 コンテキストスイッチ
先述のようにWindows Server系のOSは、開発当初からマルチスレッド処理に対応するようにデザインされています。そのため何らかの原因で(例:I/O待ちなど)、あるスレッドがCPUの使用を停止した場合には、その間を別の処理にCPU使用権を割り当てることができるため、コンピュータ全体のスループット[※3]は向上します。
では、まったく待ち状態にならずに、自らが終了するまでCPUを使用し続けるスレッドが発生した場合はどのようになるでしょうか(図1.3)。そのような場合に備えて、一般的なマルチスレッド対応OSには、あるスレッドがCPUを一定時間使用すると、強制的に別のスレッドにCPUの使用権をゆずる仕組みが実装されています。
CPU使用時間の計測にはハードウェアのタイマー(電子回路基板に設置されたカウンタ機能)が使用されます。また、スレッドに対して1回に割り当てられるCPUの使用可能な時間の単位をタイムスライスと呼びます(図1.4)。
このようにマルチスレッドOSの配下で、CPU上で実行されている処理が待機状態になるか、タイムスライスの上限として設定されているしきい値に達することによってCPUの使用権をゆずり、別の処理がCPUで実行されることをコンテキストスイッチと呼びます(図1.5)。コンテキストスイッチが発生すると、それまでCPUを使用していた処理の情報を(次にCPU使用権を得た場合に備えて)、いったんレジスタ[※4]などに保存する必要があります。
[※3]コンピュータ内で一定時間内に実行される処理の数を意味します。
[※4]CPU内に複数個存在し、演算の実行、あるいは実行状態の保存など、いくつかの用途に使用される記憶媒体です。
また、CPU使用権を得た際には、保存された前回使用時の情報をロードする必要があります。そのような、本来実行すべき処理以外の作業が必要になるため、コンテキストスイッチは負荷のかかる動作と言えます(図1.6)。Windowsで、これらの一連のCPUリソース管理を担当しているコンポーネントがWindowsスケジューラです。