1

我有简单的表:

CREATE TABLE dbo.Table1 (
   ID int IDENTITY(1,1) PRIMARY KEY,
   TextField varchar(100)
)

TextField我在列上有非聚集索引。

我正在创建一个简单的查询,它选择两个列以及在哪里我有下一个情况:

...
WHERE SUBSTRING(TextField, 1, 1) = 'x'

使用“x%”将查询转换为条件还是在列LIKE上创建分区函数更好。TextField

分区如何影响 varchar 列上的搜索条件,对于大量行,哪种解决方案会更好?

4

2 回答 2

2

默认情况下,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。

于 2013-07-23T13:49:29.050 回答
1

如果有应用于列的函数(即 SUBSTRING),则无法使用您的非聚集索引。LIKE 'x%' 在这里更可取。

于 2013-07-23T13:18:48.233 回答