简体   繁体   中英

Nonclustered index on varchar column or partitioned table

I have simple table:

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

I have nonclustered index on TextField column.

I am creating a simple query which selects both columns and in where condition i have next situation:

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

Is it better to convert query to LIKE condition with 'x%' or to create partition function on TextField column.

How partitioning can affect on search condition over varchar column, and what solution will be better for large amount of rows?

By default , SUBSTRING(TextField, 1, 1) = 'x' is not SARG able.

First, I would test that query with following solutions (SQL Profiler > {SQLStatement|Batch} Completed > CPU,Reads,Writes,Duration columns):

1) A non-clustered index on TextField column:

CREATE INDEX IN_Table1_TextField
ON dbo.Table1(TextField)
INCLUDE(non-indexed columns); -- See `SELECT` columns
GO

And the query should use LIKE :

SELECT ... FROM TextField LIKE 'x%'; -- Where "x" represent one or more chars.

Pros/cons: B-Tree/index will have many levels because o key length (maximum 100 chars + RowID if isn't a UNIQUE index) .

2) I would create an computed column for the first 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

plus

CREATE INDEX IN_Table1_FirstChar
On dbo.Table1(FirstChar)
INCLUDE (non-indexed columns); 
GO

In this case, the predicate could be

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

or

WHERE FirstChar = 'x'

Pros/cons: B-Tree/index will have far less levels because o key length (1 char + RowID). I would use if predicate selectivity is high (small number of rows verifies) but without covered columns (see INCLUDE clause).

3) A clustered index on FirstChar column thus:

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) 
);

In this case, the predicate could be

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

or

WHERE FirstChar = 'x'

Pros/cons: should give you good performance if you have many rows. In this case, the B-Tree levels will minimum (1 CHAR + 1 INT ) or minimum->medium.

Your non-clustered index can not be utilized if there is a function applied to the column (ie SUBSTRING). LIKE 'x%' would be preferable here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM