varchar列或分区表上的非聚簇索引

时间:2013-07-23 13:03:56

标签: sql-server sql-server-2012

我有简单的表格:

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列的搜索条件,哪种解决方案对大量行更好?

2 个答案:

答案 0 :(得分:2)

默认情况下,SUBSTRING(TextField, 1, 1) = 'x'不能SARG

首先,我将使用以下解决方案测试该查询(SQL Profiler> {SQLStatement | Batch}已完成> CPU,读取,写入,持续时间列):

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 /索引将有多个级别,因为密钥长度(如果不是最大100个字符+ RowID,则是UNIQUE索引)。

2)我会为第一个char创建一个计算列:

-- 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个字符+ 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树级别将最小(1 CHAR + 1 INT)或最小 - >中等。

答案 1 :(得分:1)

如果有一个函数应用于列(即SUBSTRING),则无法使用非聚集索引。喜欢'x%'会更好。