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.