前章までの内容として、SQL Serverの動作の理解に不可欠なCPU、ディスク、メモリとの関わりを取り上げてきました。これらを理解することによって、様々な障害が発生した際にSQL Server内部で発生している問題か、Windowsあるいはハードウェアのトラブルか、といった問題の切り分けが可能になります。 これ以降の章ではこれまでの知識をもとにしながら、さらにSQL Serverの内側に焦点を当てて解説します。
本章では、まずすべてのオブジェクトの“器”ともいえるデータベースの構造について詳しく紹介します。データベースの内部構造を詳細に見ていく前に、データベースを構成するファイルについて簡単におさらいしておきましょう。
SQL Serverが管理するデータベースは、少なくとも1つのデータファイルと、1つのトランザクションログファイルで構成されています。I/O操作の分散などを目的として、複数のデータファイルで構成されたデータベースを定義することもできます。そのような構成の特徴として1つ目のデータファイルは、デフォルトでは拡張子が.mdfとして設定され、データベースの管理に必要なシステムオブジェクトが格納されています。それでは、データファイルとトランザクションログファイルのそれぞれの構成について詳しく見ていきましょう。
4.1データファイル
4.1.1 ページとエクステント
データベースを構成するデータファイル(文字通りデータそのものを格納するファイル)は、内部的にページと呼ばれる、8KBの論理単位に区切って使用されます。ページはテーブルなどのオブジェクトに格納されたデータの参照や更新の際の最小論理I/O単位として使用されます。また、オブジェクトに新たな領域を割り当てる必要がある場合には、ページではなくエクステントと呼ばれる単位が使用されます。
エクステントは、8KBのページが8個で構成されています。テーブルに割り当てられたすべてのページに空きがなくなると、テーブルには新たなエクステントが割り当てられます(図4.1)。
4.1.2 単一エクステントと混合エクステント
エクステントには、1つのオブジェクトで8ページすべてを占有する単一エクステントと、複数のオブジェクトで共有する混合エクステントの2種類が存在します。SQL Server 2014までのデフォルトの動作として、オブジェクトが作成された当初は混合エクステントを割り当てていました。その理由はディスクの効率的な利用です。もしもオブジェクトのサイズが1ページよりも大きくならないのに単一エクステントを割り当てた場合、残りの7ページ(56KB)は使用されずに無駄になってしまいます。そのような無駄なディスク領域をできるだけ少なくするために、新規に作成されたオブジェクトにはまず混合エクステントが割り当てられ、そのサイズが1ページを超えた段階で単一エクステントが割り当てられます。
一方でSQL Server 2016以降では、オブジェクト作成当初から単一エクステントを割り当てることがデフォルトの動作となりました。その変更の理由は、オブジェクトに混合エクステント内のページを割り当てる際のオーバーヘッドです。単一エクステントの場合すべてのページが1つのオブジェクトに関連付けられているため、単純にその中のページを割り当てるだけで済みます(図4.2)。
混合エクステントの場合は、まず混合エクステントの有無を検索し、その中の空きページの有無を確認したうえで割り当てを実施します。そのため、単一エクステントと比較すると作業量が多く、割り当てが多発するような場合には処理時間の遅延につながる場合があります。そのためSQL Server 2016以降では、ディスクの効率的な使用よりもパフォーマンスを優先し、デフォルトの操作としてオブジェクトに最初から単一エクステントを割り当てるよう仕様が変更されました。
ただしSQL Server 2016以降であっても、ALTER DATABASEステートメントで、MIXED_PAGE_ALLOCATIONオプションを指定することで、デフォルトの動作を変更することができます(リスト4.1)。
また、SQL Server 2014以前のバージョンもトレースフラグ1118を指定することで、SQL Server 2016以降と同じ動作をするように変更することもできます(リスト 4.2)。