SlideShare a Scribd company logo
See SQL Server graphical execution plans in action | TechRepublic



   ZDNet Asia      SmartPlanet    TechRepublic                                                                                     Log In   Join TechRepublic   FAQ   Go Pro!




                                                     Blogs     Downloads       Newsletters       Galleries      Q&A         Discussions     News
                                                 Research Library


     IT Management               Development         IT Support       Data Center         Networks          Security




     Home / Blogs / The Enterprise Cloud                                                    Follow this blog:

     The Enterprise Cloud


     See SQL Server graphical
     execution plans in action
     By Tim Chapman
     October 1, 2007, 2:49 PM PDT

     Takeaway: Tim Chapman identifies a few basic things to look for in a graphical execution plan
     to help you better understand how SQL Server uses indexes. He also offers ideas about how to
     make your queries faster.

     Execution plans are one of the best tools to use to tune your SQL Server queries. In this article, I
     identify a few basic things to look for in a graphical execution plan to help you better understand
     how SQL Server uses indexes. I also offer ideas about how to make your queries faster.

     Setting up my example
     I need to create the table that I will be using throughout the examples and load some data into the
     table. I will load a fairly substantial amount of data into the table so that SQL Server will not just
     scan the table to search for data. Typically, if a table is relatively small, SQL Server will scan the
     table rather than deciding the best combination of indexes to use because it will take less time to
     scan the table.

     CREATE TABLE [dbo].[SalesHistory]
      (
            [SaleID] [int] IDENTITY(1,1),
            [Product] [varchar](10) NULL,
            [SaleDate] [datetime] NULL,
            [SalePrice] [money] NULL
      )
      GO

      SET NOCOUNT ON

      DECLARE @i INT
      SET @i = 1
      WHILE (@i <=50000)
      BEGIN

                INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)
                VALUES ('Computer', DATEADD(ww, @i, '3/11/1919'),
                DATEPART(ms, GETDATE()) + (@i + 57))

                INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)
                VALUES('BigScreen', DATEADD(ww, @i, '3/11/1927'),
                DATEPART(ms, GETDATE()) + (@i + 13))

                INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)
                VALUES('PoolTable', DATEADD(ww, @i, '3/11/1908'),
                DATEPART(ms, GETDATE()) + (@i + 29))




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
See SQL Server graphical execution plans in action | TechRepublic



            SET @i = @i + 1

      END

     The following statement creates a clustered index on the SaleID column on the SalesHistory table.
     This is somewhat of an arbitrary choice for a clustered index on the table, but it makes sense for
     this example since the SaleID will be in increasing order for the rows entered. Creating this index
     will physically order the data in the table based upon the SaleID in ascending order.

     CREATE CLUSTERED INDEX idx_SalesHistory_SaleID
      ON SalesHistory(SaleID ASC)

     Run this statement to turn on the IO statistics for our queries.

     SET STATISTICS IO ON
     In order to the view the execution plan for the queries I will run, I need to turn the option on. To do
     this, I right-click in the Query Editor window and select Include Actual Execution Plan. See Figure
     A.

     Figure A




     The following statement selects a row from the SalesHistory table based on a SaleID, on
     which there is a clustered index.

     SELECT * FROM SalesHistory
      WHERE SaleID = 9900

     You can see the graphical execution plan and statistics for this query in Figure B.

     Figure B




     The query optimizer performed a Clustered Index Seek on the query, which is technically the
     fastest type of search that you will see on a table. Notice that there were three logical reads
     involved in finding this row in the table:

     Table ‘SalesHistory’. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
See SQL Server graphical execution plans in action | TechRepublic

     The script below searches for all records in the SalesHistory table where the product is PoolTable.
     There is currently no index on this column, and there are only three different values in this field for
     all of the rows in the table. The possible values found could be PoolTable, Computer, or
     BigScreen.

     SELECT * FROM SalesHistory
      WHERE Product = 'PoolTable'

     The execution plan for the above query indicates that a Clustered Index Scan was performed. A
     Clustered Index Scan was performed because there is a clustered index on the table. Remember
     that a clustered index sorts the table in the order defined by the index keys. In this case, the
     clustered index really doesn’t help me because a scan will still need to occur to find all of the
     instances where the product is equal to PoolTable. See Figure C.

     Figure C




     Table 'SalesHistory'. Scan count 1, logical reads 815, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     So, what will happen if we create an index on the Product column in SalesHistory table? If you run
     the following statement to create a nonclusterd index on this table, you will notice that nothing has
     changed, even with an index on the Product column. The execution plan and the number of logical
     reads are the same because of the selectivity of the values in the column. There are only three
     different values for all of the rows in this table, so an additional index isn’t going to help our case
     because there are so many records to pull back. Indexes are most beneficial when they are
     declared on columns that have many distinct values.

     CREATE NONCLUSTERED INDEX idx_SalesHistory_Product
      ON SalesHistory(Product ASC)

     I am dropping the index so it doesn’t skew any results from the rest of my examples.

     DROP INDEX SalesHistory.idx_SalesHistory_Product

     The SaleDate in the SalesHistory table is reasonably unique based upon the script I used to
     generate the data. If I create an index on the SaleDate and search for a certain data, I expect that
     my search will use the index a lot more effectively than my indexes on the Product column.

     CREATE NONCLUSTERED INDEX idx_SalesHistory_SaleDate
      ON SalesHistory(SaleDate ASC)

      SELECT SaleDate, Product FROM SalesHistory
      WHERE SaleDate = '1971-05-11 00:00:00.000'

     The execution plan below confirms my suspicion. Because of the higher selectivity of the SaleDate
     column, an index seek was used. This execution plan also displays what is known as a Bookmark
     Lookup. A Bookmark Lookup occurs when SQL Server has found the record in a nonclustered
     index that satisfies the search request, but columns are requested in the SELECT field list that are
     not included in the index, so SQL Server has to go out to disk and find the additional data. In this
     execution plan, the Index Seek finds the row, and the Clustered Index Seek is the Bookmark
     Lookup. In SQL Server 2000, this description is Bookmark Lookup, and in SQL Server 2005 SP2,
     it reads Key Lookup.

     It’s generally a good idea to avoid Bookmark Lookups if you can because of the overhead of the
     extra reads involved in finding the data you need. The typical fix for them is to include the extra
     columns that you are reading in the index used to find the data. This is not going to work for
     every case, so it will take some effort to find a balance that suits your needs. See Figure D.

     Figure D




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
See SQL Server graphical execution plans in action | TechRepublic




     Table 'SalesHistory'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     Now I want to see the execution plan for the same query but without a clustered index on the
     SaleID column, so I will need to drop the clustered index.

     DROP INDEX SalesHistory.idx_SalesHistory_SaleID

      SELECT SaleDate, Product FROM SalesHistory
      WHERE SaleDate = '1971-05-11 00:00:00.000'

     You can see from the execution plan that the Clustered Index Seek turns into an RID Lookup. It is
     still a Bookmark Lookup, but it is labeled differently because the table doesn’t have a clustered
     index. One thing that is very interesting about this query is the number of logical reads produced.
     This query only produces four logical reads, while the previous query with the clustered index
     produced five logical reads. The extra read is due to the fact that the clustered index had to be
     used to find the row of data. Anytime a nonclustered index is accessed on a table that has a
     clustered index, the clustered index is ultimately used to find the rows for which you’re searching.
     Because the SalesHistory table currently doesn’t have a clustered index, this query was one
     logical read faster. See Figure E.

     Figure E




     Table 'SalesHistory'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     This does not mean that having a clustered index may be slowing your queries down. Every table
     should have a clustered index because it sorts the data in order and aids the other indexes with
     their searches. This single query happened to be a little bit quicker because there was no
     clustered index on the table. The increased speed is negligible in this case, and almost any other
     search on the table will be aided by a clustered index.

     Because my table doesn’t currently have a clustered index, I want to recreate the one that I had
     on the table. See the following code:

     CREATE CLUSTERED INDEX idx_SalesHistory_SaleID
      ON SalesHistory(SaleID ASC)

     Table ‘SalesHistory’. Scan count 1, logical reads 811, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.

     Table ‘SalesHistory’. Scan count 1, logical reads 814, physical reads 0, read-ahead reads 0, lob
     logical reads 0, lob physical reads 0, lob read-ahead reads 0.




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
See SQL Server graphical execution plans in action | TechRepublic

     The SalesHistory table was accessed twice by the clustered index recreation because, when a
     clustered index is added to a table, any nonclustered indexes on that table will need to be rebuilt.
     A nonclustred index must first access the clustered index before it can return data. The
     nonclustered index that I had on the SaleDate column was rebuilt after the clustered index was
     built. See Figure F.

     Figure F




     Tuning your queries
     The examples in this article are not a definitive guide for building indexes or reading execution
     plans and query tuning. My goal is to point you in the right direction to learn about tuning your
     own queries. Query tuning isn’t an exact science, and the needs of your database will change over
     time. The more you experiment with the possible combinations of indexes, the more successful
     you will be.

     Next time, I plan to take another look at graphical execution plans and how to read them when
     table joins occur.

     Tim Chapman a SQL Server database administrator and consultant who works for a bank in
     Louisville, KY. Tim has more than eight years of IT experience, and he is a Microsoft certified
     Database Developer and Administrator. If you would like to contact Tim, please e-mail him at
     chapman.tim@gmail.com.

     —————————————————————————————– Get SQL tips in your
     inbox TechRepublic’s free SQL Server newsletter, delivered each Tuesday, contains hands-on
     tips that will help you become more adept with this powerful relational database management
     system. Automatically subscribe today!


     Get IT Tips, news, and reviews delivered directly to your inbox by subscribing to TechRepublic’s free
     newsletters.




                    About Tim Chapman
                        Full Bio     Contact




                  Restoring the Master                              Save queries in Windows
                  database in SQL Server                            Server 2003's Active
                                                                    Directory Users and
                                                                    Computers tool




          7          Join the conversation!                                                 Add Your Opinion
      Comments       Follow via:




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
See SQL Server graphical execution plans in action | TechRepublic




       Staff Picks     Top Rated        Most Recent      My Contacts                              See All Comments




                       thisisfutile 5th Oct 2007                                                        0
                                                                                                       Votes


            That would be the sound of my head as my mind is expanding. :-P Thanks for the
            information about indexes Tim. Finally, index articles and discussions are making
            more sense. It feels good to know that... Read Whole Comment +


                View in thread




                       Yes, it makes sense.                                                             0
                       thisisfutile 5th Oct 2007                                                       Votes



            Thanks for the explanation. Now Figure E makes even more sense to me because I
            didn?t understand that relationship between clustered and non-clustered indexes.
            Also, I referenced your comment "when a... Read Whole Comment +


                View in thread




                       RE: See SQL Server graphical execution plans in action                           0
                       jayrajvakil 3rd Oct 2007                                                        Votes


            This was really a good articale Tim. Thanks for providing a good starting point on
            Query optimization. This may be just another article for the seasoned DBAs on TR
            but a great insite for a novice like... Read Whole Comment +


                View in thread




                                                   See all comments



     Join the TechRepublic Community and join the conversation! Signing-up is
     free and quick, Do it now, we want to hear your opinion.

       Join       Login




http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]

More Related Content

Viewers also liked (13)

PPTX
Как перестать требовать от клиентов бумаги с государственными печатями
Institute of development of the Internet
 
PDF
WEB 2.0
jshisantamaria
 
PPTX
E-урегулирование
Institute of development of the Internet
 
PDF
Using object dependencies in sql server 2008 tech republic
Kaing Menglieng
 
PPT
Project filem klasik dan moden
bmsiti10
 
PDF
RMIA Master Class-July 06
Gai Roper
 
PPTX
Pwr
Asri Adi
 
DOCX
Licencias creative commons
Lilianitabel
 
PDF
Web.2.0
jshisantamaria
 
PDF
Final report eia (kmc)
zubeditufail
 
PDF
DERECHO CIVIL DE LAS PERSONAS
UNY
 
Как перестать требовать от клиентов бумаги с государственными печатями
Institute of development of the Internet
 
E-урегулирование
Institute of development of the Internet
 
Using object dependencies in sql server 2008 tech republic
Kaing Menglieng
 
Project filem klasik dan moden
bmsiti10
 
RMIA Master Class-July 06
Gai Roper
 
Licencias creative commons
Lilianitabel
 
Final report eia (kmc)
zubeditufail
 
DERECHO CIVIL DE LAS PERSONAS
UNY
 

Similar to See sql server graphical execution plans in action tech republic (20)

PDF
Brad McGehee Intepreting Execution Plans Mar09
Mark Ginnebaugh
 
DOCX
Indexes in ms sql server
Rahul Yerrabelli
 
PDF
SQL Server Tuning to Improve Database Performance
Mark Ginnebaugh
 
PPT
Sql Server Performance Tuning
Bala Subra
 
PDF
Microsoft SQL Server Query Tuning
Mark Ginnebaugh
 
PPTX
Building scalable application with sql server
Chris Adkin
 
PDF
SQL Server 2014 Monitoring and Profiling
Abouzar Noori
 
PPTX
Database Performance
Boris Hristov
 
PPTX
dotnetMALAGA - Sql query tuning guidelines
Javier García Magna
 
PPTX
Managing SQLserver for the reluctant DBA
Concentrated Technology
 
PPT
Indexing Strategies
jlaspada
 
PPTX
05_DP_300T00A_Optimize.pptx
KareemBullard1
 
PDF
Enterprise dbs and Database indexing
abksharma
 
PPTX
Database Performance Tuning
Arno Huetter
 
PPTX
Oracle database performance tuning
Yogiji Creations
 
PDF
Practical SQL query monitoring and optimization
Ivo Andreev
 
PPTX
Query Optimization in SQL Server
Rajesh Gunasundaram
 
PDF
Discovering the plan cache (#SQLSat211)
Jason Strate
 
PDF
Back2 Basic Tools
sqlserver.co.il
 
PDF
Back 2 basics - SSMS Tips (IDf)
sqlserver.co.il
 
Brad McGehee Intepreting Execution Plans Mar09
Mark Ginnebaugh
 
Indexes in ms sql server
Rahul Yerrabelli
 
SQL Server Tuning to Improve Database Performance
Mark Ginnebaugh
 
Sql Server Performance Tuning
Bala Subra
 
Microsoft SQL Server Query Tuning
Mark Ginnebaugh
 
Building scalable application with sql server
Chris Adkin
 
SQL Server 2014 Monitoring and Profiling
Abouzar Noori
 
Database Performance
Boris Hristov
 
dotnetMALAGA - Sql query tuning guidelines
Javier García Magna
 
Managing SQLserver for the reluctant DBA
Concentrated Technology
 
Indexing Strategies
jlaspada
 
05_DP_300T00A_Optimize.pptx
KareemBullard1
 
Enterprise dbs and Database indexing
abksharma
 
Database Performance Tuning
Arno Huetter
 
Oracle database performance tuning
Yogiji Creations
 
Practical SQL query monitoring and optimization
Ivo Andreev
 
Query Optimization in SQL Server
Rajesh Gunasundaram
 
Discovering the plan cache (#SQLSat211)
Jason Strate
 
Back2 Basic Tools
sqlserver.co.il
 
Back 2 basics - SSMS Tips (IDf)
sqlserver.co.il
 
Ad

More from Kaing Menglieng (20)

PDF
What is your sql server backup strategy tech_republic
Kaing Menglieng
 
PDF
Using sql server 2008's merge statement tech republic
Kaing Menglieng
 
PDF
Using hash fields in sql server tech republic
Kaing Menglieng
 
PDF
Using grouping sets in sql server 2008 tech republic
Kaing Menglieng
 
PDF
Understand when to use user defined functions in sql server tech-republic
Kaing Menglieng
 
PDF
Sql server indexed views speed up your select queries part 1 - code-projec
Kaing Menglieng
 
PDF
Sql server – query optimization – remove bookmark lookup – remove rid lookup
Kaing Menglieng
 
PDF
Sql server common interview questions and answers
Kaing Menglieng
 
PDF
Sql server common interview questions and answers page 6
Kaing Menglieng
 
PDF
Sql server common interview questions and answers page 5
Kaing Menglieng
 
PDF
Sql server common interview questions and answers page 4
Kaing Menglieng
 
PDF
Sql server common interview questions and answers page 2
Kaing Menglieng
 
PDF
Sql server – 2008 – hardware and software requirements for installing sql se
Kaing Menglieng
 
PDF
Speeding up queries with semi joins and anti-joins
Kaing Menglieng
 
PDF
Speed up sql
Kaing Menglieng
 
PDF
Speed up sql server apps - visual studio magazine
Kaing Menglieng
 
PDF
Reviewing sql server permissions tech republic
Kaing Menglieng
 
PDF
Query optimization how to search millions of record in sql table faster -
Kaing Menglieng
 
PDF
Optimize sql server queries with these advanced tuning techniques tech repu
Kaing Menglieng
 
PDF
New date datatypes in sql server 2008 tech republic
Kaing Menglieng
 
What is your sql server backup strategy tech_republic
Kaing Menglieng
 
Using sql server 2008's merge statement tech republic
Kaing Menglieng
 
Using hash fields in sql server tech republic
Kaing Menglieng
 
Using grouping sets in sql server 2008 tech republic
Kaing Menglieng
 
Understand when to use user defined functions in sql server tech-republic
Kaing Menglieng
 
Sql server indexed views speed up your select queries part 1 - code-projec
Kaing Menglieng
 
Sql server – query optimization – remove bookmark lookup – remove rid lookup
Kaing Menglieng
 
Sql server common interview questions and answers
Kaing Menglieng
 
Sql server common interview questions and answers page 6
Kaing Menglieng
 
Sql server common interview questions and answers page 5
Kaing Menglieng
 
Sql server common interview questions and answers page 4
Kaing Menglieng
 
Sql server common interview questions and answers page 2
Kaing Menglieng
 
Sql server – 2008 – hardware and software requirements for installing sql se
Kaing Menglieng
 
Speeding up queries with semi joins and anti-joins
Kaing Menglieng
 
Speed up sql
Kaing Menglieng
 
Speed up sql server apps - visual studio magazine
Kaing Menglieng
 
Reviewing sql server permissions tech republic
Kaing Menglieng
 
Query optimization how to search millions of record in sql table faster -
Kaing Menglieng
 
Optimize sql server queries with these advanced tuning techniques tech repu
Kaing Menglieng
 
New date datatypes in sql server 2008 tech republic
Kaing Menglieng
 
Ad

See sql server graphical execution plans in action tech republic

  • 1. See SQL Server graphical execution plans in action | TechRepublic ZDNet Asia SmartPlanet TechRepublic Log In Join TechRepublic FAQ Go Pro! Blogs Downloads Newsletters Galleries Q&A Discussions News Research Library IT Management Development IT Support Data Center Networks Security Home / Blogs / The Enterprise Cloud Follow this blog: The Enterprise Cloud See SQL Server graphical execution plans in action By Tim Chapman October 1, 2007, 2:49 PM PDT Takeaway: Tim Chapman identifies a few basic things to look for in a graphical execution plan to help you better understand how SQL Server uses indexes. He also offers ideas about how to make your queries faster. Execution plans are one of the best tools to use to tune your SQL Server queries. In this article, I identify a few basic things to look for in a graphical execution plan to help you better understand how SQL Server uses indexes. I also offer ideas about how to make your queries faster. Setting up my example I need to create the table that I will be using throughout the examples and load some data into the table. I will load a fairly substantial amount of data into the table so that SQL Server will not just scan the table to search for data. Typically, if a table is relatively small, SQL Server will scan the table rather than deciding the best combination of indexes to use because it will take less time to scan the table. CREATE TABLE [dbo].[SalesHistory] ( [SaleID] [int] IDENTITY(1,1), [Product] [varchar](10) NULL, [SaleDate] [datetime] NULL, [SalePrice] [money] NULL ) GO SET NOCOUNT ON DECLARE @i INT SET @i = 1 WHILE (@i <=50000) BEGIN INSERT INTO [SalesHistory](Product, SaleDate, SalePrice) VALUES ('Computer', DATEADD(ww, @i, '3/11/1919'), DATEPART(ms, GETDATE()) + (@i + 57)) INSERT INTO [SalesHistory](Product, SaleDate, SalePrice) VALUES('BigScreen', DATEADD(ww, @i, '3/11/1927'), DATEPART(ms, GETDATE()) + (@i + 13)) INSERT INTO [SalesHistory](Product, SaleDate, SalePrice) VALUES('PoolTable', DATEADD(ww, @i, '3/11/1908'), DATEPART(ms, GETDATE()) + (@i + 29)) http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
  • 2. See SQL Server graphical execution plans in action | TechRepublic SET @i = @i + 1 END The following statement creates a clustered index on the SaleID column on the SalesHistory table. This is somewhat of an arbitrary choice for a clustered index on the table, but it makes sense for this example since the SaleID will be in increasing order for the rows entered. Creating this index will physically order the data in the table based upon the SaleID in ascending order. CREATE CLUSTERED INDEX idx_SalesHistory_SaleID ON SalesHistory(SaleID ASC) Run this statement to turn on the IO statistics for our queries. SET STATISTICS IO ON In order to the view the execution plan for the queries I will run, I need to turn the option on. To do this, I right-click in the Query Editor window and select Include Actual Execution Plan. See Figure A. Figure A The following statement selects a row from the SalesHistory table based on a SaleID, on which there is a clustered index. SELECT * FROM SalesHistory WHERE SaleID = 9900 You can see the graphical execution plan and statistics for this query in Figure B. Figure B The query optimizer performed a Clustered Index Seek on the query, which is technically the fastest type of search that you will see on a table. Notice that there were three logical reads involved in finding this row in the table: Table ‘SalesHistory’. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
  • 3. See SQL Server graphical execution plans in action | TechRepublic The script below searches for all records in the SalesHistory table where the product is PoolTable. There is currently no index on this column, and there are only three different values in this field for all of the rows in the table. The possible values found could be PoolTable, Computer, or BigScreen. SELECT * FROM SalesHistory WHERE Product = 'PoolTable' The execution plan for the above query indicates that a Clustered Index Scan was performed. A Clustered Index Scan was performed because there is a clustered index on the table. Remember that a clustered index sorts the table in the order defined by the index keys. In this case, the clustered index really doesn’t help me because a scan will still need to occur to find all of the instances where the product is equal to PoolTable. See Figure C. Figure C Table 'SalesHistory'. Scan count 1, logical reads 815, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. So, what will happen if we create an index on the Product column in SalesHistory table? If you run the following statement to create a nonclusterd index on this table, you will notice that nothing has changed, even with an index on the Product column. The execution plan and the number of logical reads are the same because of the selectivity of the values in the column. There are only three different values for all of the rows in this table, so an additional index isn’t going to help our case because there are so many records to pull back. Indexes are most beneficial when they are declared on columns that have many distinct values. CREATE NONCLUSTERED INDEX idx_SalesHistory_Product ON SalesHistory(Product ASC) I am dropping the index so it doesn’t skew any results from the rest of my examples. DROP INDEX SalesHistory.idx_SalesHistory_Product The SaleDate in the SalesHistory table is reasonably unique based upon the script I used to generate the data. If I create an index on the SaleDate and search for a certain data, I expect that my search will use the index a lot more effectively than my indexes on the Product column. CREATE NONCLUSTERED INDEX idx_SalesHistory_SaleDate ON SalesHistory(SaleDate ASC) SELECT SaleDate, Product FROM SalesHistory WHERE SaleDate = '1971-05-11 00:00:00.000' The execution plan below confirms my suspicion. Because of the higher selectivity of the SaleDate column, an index seek was used. This execution plan also displays what is known as a Bookmark Lookup. A Bookmark Lookup occurs when SQL Server has found the record in a nonclustered index that satisfies the search request, but columns are requested in the SELECT field list that are not included in the index, so SQL Server has to go out to disk and find the additional data. In this execution plan, the Index Seek finds the row, and the Clustered Index Seek is the Bookmark Lookup. In SQL Server 2000, this description is Bookmark Lookup, and in SQL Server 2005 SP2, it reads Key Lookup. It’s generally a good idea to avoid Bookmark Lookups if you can because of the overhead of the extra reads involved in finding the data you need. The typical fix for them is to include the extra columns that you are reading in the index used to find the data. This is not going to work for every case, so it will take some effort to find a balance that suits your needs. See Figure D. Figure D http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
  • 4. See SQL Server graphical execution plans in action | TechRepublic Table 'SalesHistory'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Now I want to see the execution plan for the same query but without a clustered index on the SaleID column, so I will need to drop the clustered index. DROP INDEX SalesHistory.idx_SalesHistory_SaleID SELECT SaleDate, Product FROM SalesHistory WHERE SaleDate = '1971-05-11 00:00:00.000' You can see from the execution plan that the Clustered Index Seek turns into an RID Lookup. It is still a Bookmark Lookup, but it is labeled differently because the table doesn’t have a clustered index. One thing that is very interesting about this query is the number of logical reads produced. This query only produces four logical reads, while the previous query with the clustered index produced five logical reads. The extra read is due to the fact that the clustered index had to be used to find the row of data. Anytime a nonclustered index is accessed on a table that has a clustered index, the clustered index is ultimately used to find the rows for which you’re searching. Because the SalesHistory table currently doesn’t have a clustered index, this query was one logical read faster. See Figure E. Figure E Table 'SalesHistory'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. This does not mean that having a clustered index may be slowing your queries down. Every table should have a clustered index because it sorts the data in order and aids the other indexes with their searches. This single query happened to be a little bit quicker because there was no clustered index on the table. The increased speed is negligible in this case, and almost any other search on the table will be aided by a clustered index. Because my table doesn’t currently have a clustered index, I want to recreate the one that I had on the table. See the following code: CREATE CLUSTERED INDEX idx_SalesHistory_SaleID ON SalesHistory(SaleID ASC) Table ‘SalesHistory’. Scan count 1, logical reads 811, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table ‘SalesHistory’. Scan count 1, logical reads 814, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
  • 5. See SQL Server graphical execution plans in action | TechRepublic The SalesHistory table was accessed twice by the clustered index recreation because, when a clustered index is added to a table, any nonclustered indexes on that table will need to be rebuilt. A nonclustred index must first access the clustered index before it can return data. The nonclustered index that I had on the SaleDate column was rebuilt after the clustered index was built. See Figure F. Figure F Tuning your queries The examples in this article are not a definitive guide for building indexes or reading execution plans and query tuning. My goal is to point you in the right direction to learn about tuning your own queries. Query tuning isn’t an exact science, and the needs of your database will change over time. The more you experiment with the possible combinations of indexes, the more successful you will be. Next time, I plan to take another look at graphical execution plans and how to read them when table joins occur. Tim Chapman a SQL Server database administrator and consultant who works for a bank in Louisville, KY. Tim has more than eight years of IT experience, and he is a Microsoft certified Database Developer and Administrator. If you would like to contact Tim, please e-mail him at [email protected]. —————————————————————————————– Get SQL tips in your inbox TechRepublic’s free SQL Server newsletter, delivered each Tuesday, contains hands-on tips that will help you become more adept with this powerful relational database management system. Automatically subscribe today! Get IT Tips, news, and reviews delivered directly to your inbox by subscribing to TechRepublic’s free newsletters. About Tim Chapman Full Bio Contact Restoring the Master Save queries in Windows database in SQL Server Server 2003's Active Directory Users and Computers tool 7 Join the conversation! Add Your Opinion Comments Follow via: http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]
  • 6. See SQL Server graphical execution plans in action | TechRepublic Staff Picks Top Rated Most Recent My Contacts See All Comments thisisfutile 5th Oct 2007 0 Votes That would be the sound of my head as my mind is expanding. :-P Thanks for the information about indexes Tim. Finally, index articles and discussions are making more sense. It feels good to know that... Read Whole Comment + View in thread Yes, it makes sense. 0 thisisfutile 5th Oct 2007 Votes Thanks for the explanation. Now Figure E makes even more sense to me because I didn?t understand that relationship between clustered and non-clustered indexes. Also, I referenced your comment "when a... Read Whole Comment + View in thread RE: See SQL Server graphical execution plans in action 0 jayrajvakil 3rd Oct 2007 Votes This was really a good articale Tim. Thanks for providing a good starting point on Query optimization. This may be just another article for the seasoned DBAs on TR but a great insite for a novice like... Read Whole Comment + View in thread See all comments Join the TechRepublic Community and join the conversation! Signing-up is free and quick, Do it now, we want to hear your opinion. Join Login http://www.techrepublic.com/blog/datacenter/see-sql-server-graphical-execution-plans-in-action/198[08/29/2012 3:18:19 PM]