デフォルトでSUBSTRING(TextField, 1, 1) = 'x'
は、SARG
できません。
まず、次のソリューションを使用してそのクエリをテストします (SQL プロファイラー > {SQLStatement|Batch} Completed > CPU,Reads,Writes,Duration 列)。
1)TextField
列の非クラスター化インデックス:
CREATE INDEX IN_Table1_TextField
ON dbo.Table1(TextField)
INCLUDE(non-indexed columns); -- See `SELECT` columns
GO
そして、クエリは次を使用する必要がありますLIKE
:
SELECT ... FROM TextField LIKE 'x%'; -- Where "x" represent one or more chars.
長所/短所: キーの長さ (最大 100 文字 + UNIQUE インデックスでない場合は RowID) のため、B ツリー/インデックスには多くのレベルがあります。
2)最初の文字の計算列を作成します。
-- TextField column needs to be mandatory
ALTER TABLE dbo.Table1
ADD FirstChar AS (CONVERT(CHAR(1),SUBSTRING(TextField,1,1))); -- This computed column could be non-persistent
GO
プラス
CREATE INDEX IN_Table1_FirstChar
On dbo.Table1(FirstChar)
INCLUDE (non-indexed columns);
GO
この場合、述語は次のようになります。
WHERE SUBSTRING(TextField, 1, 1) = 'x'
また
WHERE FirstChar = 'x'
長所/短所: キーの長さ (1 文字 + RowID) のため、B ツリー/インデックスのレベルははるかに少なくなります。述語の選択性が高い (少数の行が検証される) が、カバーされた列がない場合 (INCLUDE
節を参照) に使用します。
3)したがって、列のクラスター化インデックス:FirstChar
CREATE TABLE dbo.Table1 (
ID int IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
TextField varchar(100) NOT NULL, -- This column needs to be mandatory
ADD FirstChar AS (CONVERT(CHAR(1),SUBSTRING(TextField,1,1))),
UNIQUE CLUSTERED(FirstChar,ID)
);
この場合、述語は次のようになります。
WHERE SUBSTRING(TextField, 1, 1) = 'x'
また
WHERE FirstChar = 'x'
長所/短所: 行数が多い場合は、パフォーマンスが向上するはずです。この場合、B ツリーのレベルは最小 (1 CHAR
+ 1 INT
) または最小 -> 中になります。