默认情况下,SUBSTRING(TextField, 1, 1) = 'x'
是不能的SARG
。
首先,我将使用以下解决方案(SQL Profiler > {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.
优点/缺点:B-Tree/index 将有很多级别,因为 o 键长度(如果不是唯一索引,则最大 100 个字符 + RowID)。
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'
优点/缺点:B-Tree/index 的级别会少得多,因为密钥长度(1 char + RowID)。如果谓词选择性很高(验证的行数很少)但没有覆盖的列(请参阅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-Tree 级别将最小 (1 CHAR
+ 1 INT
) 或 minimum->medium。