I've been trying to understand why SQL server decides build a very complex query plan in some cases.
I've got two test Tables.
- Tab1 and Tabx
When the table only has a single data page the select statement behaves as I would expect and uses the Index efficiently.
However as soon as there's two data pages pages, the query run against xTab explodes into this:
I'm trying to understand why this is. Below are two test scripts that create the two tables:
CREATE TABLE dbo.Tab1 ( id BIGINT NOT NULL, Alias VARCHAR(36) NOT NULL, Version INT, Locale VARCHAR(5), Value1 VARCHAR(100) NOT NULL ); CREATE NONCLUSTERED INDEX [IDX1] ON [dbo].[Tab1] ( [id] ASC, [Alias] ASC, [Version] DESC, [Locale] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO Truncate table Tab1 Go DECLARE @i AS int = 1; WHILE @i < 200 BEGIN SET @i = @i + 1; INSERT INTO dbo.Tab1 (id, Alias, Version,Locale,Value1) VALUES (@i, 'x', 1,'en-us','Test1'); END; Go -- Take a look at how many pages we have SELECT index_type_desc, page_count,record_count, avg_page_space_used_in_percent FROM sys.dm_db_index_physical_stats(DB_ID(N'Test1'), OBJECT_ID(N'dbo.Tab1'), NULL, NULL , 'DETAILED'); Select Id From Tab1 a Where a.id = 1 and a.Alias = 'x' and (a.Locale = 'en-us' or a.Locale is NULL) and a.Version = 1 Order By Version desc
vs
USE [test1] GO /****** Object: Table [dbo].[xTab1] Script Date: 09/05/2013 08:56:38 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[xTab1]( [ObjectPropertyCode] [bigint] IDENTITY(1,1) NOT NULL, [ObjectCode] [bigint] NOT NULL, [String200Name] [varchar](30) NOT NULL, [String200] [varchar](2000) NOT NULL, [GroupCode] [bigint] NOT NULL, [Status] [char](1) NOT NULL, [EntityObjectCode] [bigint] NOT NULL, [Type] [varchar](5) NOT NULL, [ObjectPropertyAlias] [varchar](60) NOT NULL, [TypeObjectCode] [bigint] NOT NULL, [Version] [int] NULL, [Locale] [varchar](5) NULL ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_StringName] DEFAULT ('') FOR [String200Name] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_String] DEFAULT ('') FOR [String200] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF__47jectPro__Group__08EA5793] DEFAULT ((0)) FOR [GroupCode] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_Status] DEFAULT ('A') FOR [Status] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_EntityObjectCode] DEFAULT ((-1)) FOR [EntityObjectCode] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_47] DEFAULT ('') FOR [Type] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_ObjectPropertyAlias] DEFAULT ('') FOR [ObjectPropertyAlias] GO ALTER TABLE [dbo].[xTab1] ADD CONSTRAINT [DF_xTab1_TypeObjectCode] DEFAULT ((-1)) FOR [TypeObjectCode] GO /****** Object: Index [IDX1] Script Date: 09/05/2013 08:51:45 ******/ CREATE NONCLUSTERED INDEX [IDX1] ON [dbo].[xTab1] ( [ObjectCode] ASC, [ObjectPropertyAlias] ASC, [Version] DESC, [Locale] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO Truncate table xTab1 Go DECLARE @i AS int = 1; WHILE @i < 101 BEGIN SET @i = @i + 1; INSERT INTO dbo.xTab1 (ObjectCode, ObjectPropertyAlias, Version,Locale,String200,GroupCode) VALUES (@i, 'x', 1,'en-us','Test1',0); END; Go -- Take a look at how many pages we have SELECT index_type_desc, page_count,record_count, avg_page_space_used_in_percent FROM sys.dm_db_index_physical_stats(DB_ID(N'Test1'), OBJECT_ID(N'dbo.xTab1'), NULL, NULL , 'DETAILED'); Select ObjectCode From xTab1 a Where a.ObjectCode = 514345440 and a.ObjectPropertyAlias = 'x' and (a.Locale = 'en-us' or a.Locale is NULL) and a.Version = 1 Order By Version desc