データベースインデックスは、レコード数が多いテーブルでのデータベース操作の速度を向上させるために使用されます。データベースインデックス(クラスター化インデックスと非クラスター化インデックスの両方)は、機能的にブックインデックスと非常によく似ています。本の索引を使用すると、本で説明されているさまざまなトピックに直接移動できます。特定のトピックを検索する場合は、インデックスに移動し、探しているトピックを含むページ番号を見つけて、そのページに直接移動できます。インデックスがないと、本全体を検索する必要があります。
データベースインデックスは同じように機能します。インデックスがないと、特定のデータベース操作を実行するためにテーブル全体を検索する必要があります。インデックスを使用すると、すべてのテーブルレコードをスキャンする必要はありません。インデックスは、検索しているレコードを直接指し示し、クエリの実行時間を大幅に短縮します。
SQL Serverのインデックスは、主に2つのタイプに分けることができます。
- クラスター化インデックス
- 非クラスター化インデックス
この記事では、クラスター化されたインデックスとクラスター化されていないインデックスとは何か、それらがどのように作成されるか、そして2つの主な違いは何かを見ていきます。また、SQLServerでクラスター化インデックスまたは非クラスター化インデックスを使用する場合についても説明します。
まず、クラスター化されたインデックスから始めましょう。
クラスター化されたインデックス
クラスタ化インデックスは、テーブルレコードがデータベースに格納される物理的な順序を定義するインデックスです。レコードをデータベーステーブルに物理的に格納する方法は1つしかないため、テーブルごとに1つのクラスター化インデックスしか存在できません。デフォルトでは、クラスター化インデックスは主キー列に作成されます。
デフォルトのクラスター化インデックス
デフォルトのクラスター化インデックスを確認するために、主キー列を持つダミーテーブルを作成してみましょう。次のスクリプトを実行します。
CREATE DATABASE Hospital
CREATE TABLE Patients
(
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(50) NOT NULL,
age INT NOT NULL
)
上記のスクリプトは、ダミーのデータベースHospitalを作成します。データベースには、id、name、gender、ageの4つの列があります。 id列は主キー列です。上記のスクリプトを実行すると、id列にクラスター化インデックスが自動的に作成されます。テーブル内のすべてのインデックスを表示するには、「sp_helpindex」ストアドプロシージャを使用できます。
USE Hospital
EXECUTE sp_helpindex Patients
出力は次のとおりです:
インデックス名、説明、およびインデックスが作成された列を確認できます。新しいレコードをPatientsテーブルに追加すると、id列の値の昇順で保存されます。テーブルに挿入する最初のレコードのIDが3の場合、クラスター化されたインデックスは物理的な順序を維持するため、レコードは最初の行ではなく3番目の行に格納されます。
カスタムクラスター化インデックス
独自のクラスター化インデックスを作成できます。ただし、その前に、既存のクラスター化インデックスを作成する必要があります。主キー列のために1つのクラスター化インデックスがあります。主キー制約を削除すると、デフォルトのクラスターが削除されます。次のスクリプトは、主キーの制約を削除します。
USE Hospital
ALTER TABLE Patients
DROP CONSTRAINT PK__Patients__3213E83F3DFAFAAD
GO
次のスクリプトは、Patientsテーブルのage列にカスタムインデックス「IX_tblPatient_Age」を作成します。このインデックスにより、Patientsテーブルのすべてのレコードは年齢の昇順で保存されます。
use Hospital
CREATE CLUSTERED INDEX IX_tblPatient_Age
ON Patients(age ASC)
次に、Patientsテーブルにいくつかのダミーレコードを追加して、それらが実際に年齢の昇順で挿入されているかどうかを確認します。
USE Hospital
INSERT INTO Patients
VALUES
(1, 'Sara', 'Female', 34),
(2, 'Jon', 'Male', 20),
(3, 'Mike', 'Male', 54),
(4, 'Ana', 'Female', 10),
(5, 'Nick', 'Female', 29)
上記のスクリプトでは、5つのダミーレコードを追加します。年齢列の値に注意してください。それらはランダムな値を持ち、論理的な順序ではありません。ただし、クラスター化インデックスを作成したため、レコードは実際には年齢列の値の昇順で挿入されます。これは、Patientsテーブルからすべてのレコードを選択することで確認できます。
SELECT * FROM Patients
出力は次のとおりです:
レコードが年齢列の値の昇順で並べられていることがわかります。
非クラスター化インデックス
非クラスター化インデックスは、検索操作を高速化するためにも使用されます。クラスター化されたインデックスとは異なり、クラスター化されていないインデックスは、レコードがテーブルに挿入される順序を物理的に定義しません。実際、非クラスター化インデックスは、データテーブルとは別の場所に格納されます。非クラスター化インデックスは、本の主要な内容とは別に配置される本のインデックスのようなものです。非クラスター化インデックスは別の場所にあるため、テーブルごとに複数の非クラスター化インデックスが存在する可能性があります。
非クラスター化インデックスを作成するには、「CREATENONCLUSTERED」ステートメントを使用する必要があります。残りの構文は、クラスター化インデックスを作成するための構文と同じままです。次のスクリプトは、名前の昇順でレコードを並べ替える非クラスター化インデックス「IX_tblPatient_Name」を作成します。
use Hospital
CREATE NONCLUSTERED INDEX IX_tblPatient_Name
ON Patients(name ASC)
上記のスクリプトは、以下に示すように、患者の名前と対応するレコードのアドレスを含むインデックスを作成します。
名前 | レコードアドレス |
Ana | レコードアドレス |
Jon | レコードアドレス |
Mike | レコードアドレス |
Nick | レコードアドレス |
Sara | レコードアドレス |
ここで、各行の「レコードアドレス」は、対応する名前を持つ患者の実際のテーブルレコードへの参照です。
たとえば、「Mike」という名前の患者の年齢と性別を取得する場合、データベースは最初に非クラスター化インデックス「IX_tblPatient_Name」で「Mick」を検索し、非クラスター化インデックスから実際のレコード参照を取得します。これを使用して、「マイク」という名前の患者の実際の年齢と性別を返します
データベースは、最初に非クラスター化インデックスで、次に実際のテーブルで2つの検索を行う必要があるため、非クラスター化インデックスの検索操作は遅くなる可能性があります。ただし、INSERTおよびUPDATE操作の場合、レコードの順序は実際のテーブルではなくインデックスで更新するだけでよいため、非クラスター化インデックスの方が高速です。
クラスター化インデックスまたは非クラスター化インデックスを使用する場合
クラスター化されたインデックスとクラスター化されていないインデックスの違いがわかったので、それぞれを使用するためのさまざまなシナリオを見てみましょう。
1。インデックスの数
これはかなり明白です。データベースに複数のインデックスを作成する必要がある場合は、クラスター化インデックスは1つしか存在できないため、非クラスター化インデックスを選択してください。
2。 SELECT操作
作成とインデックス作成に使用されるインデックス値のみを選択する場合は、非クラスター化インデックスの方が高速です。たとえば、「名前」列にインデックスを作成し、名前のみを選択する場合、非クラスター化インデックスはすぐに名前を返します。
ただし、名前インデックスを使用して年齢、性別などの他の列値を選択する場合は、最初に名前がインデックスから検索され、次に実際のテーブルレコードへの参照が検索に使用されるため、SELECT操作は遅くなります。年齢と性別。
一方、クラスター化インデックスでは、すべてのレコードが既に並べ替えられているため、クラスター化インデックスのある列以外の列からデータを選択すると、SELECT操作が高速になります。
3。 INSERT/UPDATE操作
INSERTまたはUPDATE操作が実行されるときに実際のレコードをソートする必要がないため、非クラスター化インデックスを使用すると、INSERTおよびUPDATE操作が高速になります。むしろ、非クラスター化インデックスのみを更新する必要があります。
4。ディスク容量
非クラスター化インデックスは元のテーブルとは別の場所に格納されるため、非クラスター化インデックスは追加のディスクスペースを消費します。ディスク容量に問題がある場合は、クラスター化されたインデックスを使用してください。
5。最終評決
経験則として、すべてのテーブルには、レコードの選択に使用され、一意の値を含む列に、少なくとも1つのクラスター化されたインデックスが必要です。主キー列は、クラスター化インデックスの理想的な候補です。
一方、INSERTクエリとUPDATEクエリに頻繁に関係する列には、ディスクスペースが問題にならないことを前提として、非クラスター化インデックスが必要です。