Detailed SQL Server focused filtering index _mssql

Source: Internet
Author: User
Tags sql 2008

Objective

In this section, we will continue to talk about indexing knowledge, in front of our clustered index, nonclustered index and overlay index, in which there is also a filtered index, through the index filter we can improve query performance, short content, in-depth understanding.

Filter indexes to create nonclustered indexes on query criteria (1)

The filtering index is a new feature of SQL 2008 that is applied to some of the rows in the table, so using a filtered index improves the query and reduces the cost of index maintenance and index storage relative to the full table scan. The index is filtered when we apply the Where condition on the index. That is, the following format is satisfied:

CREATE nonclustered INDEX <index name> on
<table> (<columns>)
WHERE <criteria>;
Go

Now let's look at a simple query

Use AdventureWorks2012
go
SELECT salesorderdetailid, UnitPrice from
sales.salesorderdetail
WHERE UnitPrice > Go

None of the indexes are established in the above column, except, of course, the clustered index created by default Salesorderdetailid, in which case we can guess that the query plan it executes must be a clustered index scan created by the primary key, as follows

As we have said at this time, the index is not created on the query criteria, so it is inevitable that the primary key creates a clustered index, and then we first create a nonclustered index on the UnitPrice column to improve query performance.

CREATE nonclustered INDEX idx_salesorderdetail_unitprice on
sales.salesorderdetail (UnitPrice)

Now we're going to compare the query overhead.

Use AdventureWorks2012
go
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SELECT Salesorderdetailid, UnitPrice from
AdventureWorks2012.Sales.SalesOrderDetail with ([pk_salesorderdetail_salesorderid_ Salesorderdetailid])
WHERE unitprice > Go
SELECT salesorderdetailid, UnitPrice from
Sales.SalesOrderDetail with INDEX ([Idx_salesorderdetail_unitprice])
WHERE UnitPrice > 2000

After a nonclustered index is established on the query condition, the query overhead is significantly elevated, up to more than 90%, because the nonclustered index also references the clustered index created by the primary key, so this time does not cause either the bookmark lookup or the key lookup lookup. Next we're going to add a nonclustered index with a condition that filters the index

CREATE nonclustered INDEX idxwhere_salesorderdetail_unitprice on
sales.salesorderdetail (UnitPrice)
WHERE UnitPrice > 1000

Now let's take a look at the difference between the performance cost of nonclustered indexes after the filtered index has been created:

Use AdventureWorks2012
go
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SELECT Salesorderdetailid, UnitPrice from
AdventureWorks2012.Sales.SalesOrderDetail with ([Idx_salesorderdetail_unitprice])
WHERE UnitPrice >
SELECT salesorderdetailid, UnitPrice from
Sales.SalesOrderDetail with (INDEX ( Idxwhere_salesorderdetail_unitprice])
WHERE UnitPrice > 2000

At this point we know that the nonclustered filtered index we created is nearly half as close to our query as the traditional nonclustered index created.

Unique Filter Index

Unique filtering indexes must be unique and not empty (allow only one null presence) for all columns, so you will need to exclude null values when creating a unique filtered index, such as the following:

CREATE UNIQUE nonclustered INDEX uq_fix_customers_email on
Customers (email)
WHERE email isn't NULL go

Filter index combination include

When we add an extra column, the clustered index created by the default primary key is used. This will take a clustered index scan, and then we create a filter index on the query criteria, and when we force this filter index, the addition of additional columns will result in the need to return to the base table to fetch the data, so it creates a key Lookup lookup, as follows:

Use AdventureWorks2012
go
SELECT salesorderdetailid, UnitPrice, Unitpricediscount from
Sales.SalesOrderDetail
WHERE UnitPrice > Go

At this point we need to include the extra columns with include.

CREATE nonclustered INDEX [Idx_salesorderdetail_unitprice] on Sales.SalesOrderDetail (UnitPrice) INCLUDE ( Unitpricediscount)

We'll create a filtered index and include extra columns

CREATE nonclustered INDEX [Idxwhere_salesorderdetail_unitprice] on Sales.SalesOrderDetail (UnitPrice) INCLUDE ( Unitpricediscount)
WHERE UnitPrice > 2000

Then we'll do the comparison. Adding a filtered index and not adding a filtered index also includes performance query variances for additional columns.

SELECT Salesorderdetailid, UnitPrice, unitpricediscount from
AdventureWorks2012.Sales.SalesOrderDetail with ( INDEX ([Idx_salesorderdetail_unitprice]))
WHERE unitprice > 
SELECT salesorderdetailid, UnitPrice, Unitpricediscount from
sales.salesorderdetail with ([Idxwhere_salesorderdetail_unitprice])
WHERE UnitPrice > 2000

Performance with include to include additional column performance has also improved somewhat.

Filter index, create nonclustered index on primary key (2)

In the first column, we can create a nonclustered index directly on the query column because its type is numeric, what if the query condition is a character type? First choice now we create a test table

Use TSQL2012
go
CREATE TABLE dbo. TestData 
(
  RowID    integer IDENTITY not null, 
  somevalue  VARCHAR (max) is not NULL,   
  StartDate  date not NULL,
  CONSTRAINT pk_data_rowid
    PRIMARY KEY CLUSTERED (RowID)
);

Add 100,000 test data

Use TSQL2012
go
INSERT dbo. TestData with (Tablockx)
  (somevalue, StartDate)
SELECT
  CAST (n.n as VARCHAR (max)) + ' Jeffckywang ',
  DATEADD (Day, (n.n-1)%, ' 20140101 ') from
dbo. Nums as N
WHERE 
  n.n >= 1 and 
  N.N < 100001;

If we need to get somevalue = ' Jeffckywang ' in the table testdata, we want to create a nonclustered index on somevalue and then filter it, as follows

Use TSQL2012
go
CREATE nonclustered INDEX idx_noncls_somevalue on
dbo. TestData (somevalue)
WHERE somevalue = ' Jeffckywang '

Update

SQL Server has a limit on the size of the index to create, the maximum is 900 bytes, the above directly written varchar (max), so there will be errors, remember, remember.

At this point we create a nonclustered index on the primary key, we create a filtered index on the primary key rowid and somevalue = ' Jeffckywang ', and then return the data as follows:

CREATE nonclustered INDEX idxwhere_noncls_somevalue on
dbo. TestData (RowID)
WHERE somevalue = ' Jeffckywang '

Here we compare the results of the query plan before and after setting up the filtering index:

Use TSQL2012
go
SELECT RowID, Somevalue, startdate from 
dbo. TestData with (INDEX ([Idx_pk_rowid]))
WHERE somevalue = ' Jeffckywang '
SELECT rowid, somevalue, StartDate 
FROM dbo. TestData with (INDEX ([Idxwhere_noncls_somevalue]))
WHERE somevalue = ' Jeffckywang '

Then, with the previous learning, remove key Lookup and include the filtered index created.

CREATE nonclustered INDEX [Idxwhere_noncls_somevalue] on dbo. TestData (RowID) INCLUDE (somevalue,startdate) 
WHERE somevalue = ' Jeffckywang '

From here, whether you create a filter index on a query condition or a filter index on a primary key, we can improve query performance by combining what we learned before.

We've been talking from the beginning. To create a filtered index, what are the criteria for creating the advantages of filtering indexes?

(1) can only be created through a nonclustered index.

(2) If you create a filtered index on a view, this view must be a persisted view.

(3) You cannot create a filtered index on a full-text index.

Advantages of filtering indexes

(1) Reduce the cost of index maintenance: For the increase, delete, change and other operations do not need to cost less expensive, because a filter index to rebuild does not take too much time.

(2) Reduce storage cost: The storage footprint of the filtering index is very small.

(3) More accurate statistics: By creating a filtered index on the Where condition, it is more accurate than the whole table statistic.

(4) Optimization of query performance: Through the query plan can see its efficiency.

So far, it has been stated that the advantages and benefits of filtering the index, has been the blessing of the sky, in fact its shortcomings are obvious.

Filtering Index Disadvantage

The biggest disadvantage is the restriction of query conditions. Its query criteria are limited to

<filter_predicate>:: =  
  <conjunct> [and <conjunct>] 
<conjunct>:: = 
  <disjunct > | <comparison>  
<disjunct>:: = 
    column_name in (constant,... N)

Filter conditions are limited to and, |, in. The comparison condition is limited to {is | is not | = | <> |!= | > | >= |!> | < | <= |!<}, so use like no

CREATE nonclustered INDEX [Idxwhere_noncls_somevalue] on dbo. TestData (RowID) INCLUDE (somevalue,startdate) 
WHERE somevalue like ' jeffckywang% '

The following can be

Use AdventureWorks2012
go
CREATE nonclustered INDEX idx_salesorderdetail_modifieddate
on Sales.SalesOrderDetail (modifieddate)
WHERE modifieddate >= ' 2008-01-01 ' and ModifiedDate ' 2008-01-07 ' Go

as follows but not

CREATE nonclustered INDEX idx_salesorderdetail_modifieddate on
sales.salesorderdetail (modifieddate)
WHERE ModifiedDate = GETDATE () go

Effects of variables on filtering indexes

Above we create a filter index that is directly defined on the query criteria, as follows:

CREATE nonclustered INDEX idxwhere_salesorderdetail_unitprice on
sales.salesorderdetail (UnitPrice)
WHERE UnitPrice > 1000

If you define a variable, what happens when you use a variable to compare it? First we create a filtered index

CREATE nonclustered INDEX Idx_salesorderdetail_productid on 
sales.salesorderdetail (ProductID)
WHERE ProductID = 870

Using variables to compare with query conditions, force filtering indexes (by default, go to clustered indexes)

Use AdventureWorks2012
go
DECLARE @ProductID INT 
SET @ProductID = 870 
SELECT ProductID 
from Sales.SalesOrderDetail with (INDEX ([Idx_salesorderdetail_productid]))
WHERE ProductID = @ProductID

To view the query execution plan results there was an error, at which point we need to add option to recompile, as follows:

Use AdventureWorks2012
go
DECLARE @ProductID INT 
SET @ProductID = 870 
SELECT ProductID 
from Sales.SalesOrderDetail
WHERE ProductID = @ProductID
OPTION (RECOMPILE)

The above use variables to query the last by option recompile in SQL Server 2012 test so that, as other versions are unknown, reference "The Pains of filtered Indexes".

Summarize

In this section, we learn to improve query performance by filtering indexes, as well as their different scenarios and their use advantages and obvious drawbacks. Short content, in-depth understanding, we see the next section, Good night.

The above is the entire content of this article, I hope the content of this article for everyone's study or work can bring some help, if there are questions you can message exchange, but also hope that a lot of support cloud Habitat community!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.