I wrote the next script in SQL Server 2012, but it fails on constraint.
I have a table with 20 000 000 rows.
I created the same table with same index with partition, but when I switched
the table, SQL Server failed
Here is my code:
CREATE DATABASE test
USE test
create Partition Function
[PF_Table_Log] ([DATETIME2](3)) As Range left For VALUES
('2016-04-05 00:00:00.000','2016-04-06 00:00:00.000',
'2016-04-07 00:00:00.000','2016-04-08 00:00:00.000')
Create Partition Scheme PS_Table_Log_Datetime
As Partition [PF_Table_Log]
All To ([Primary]);
create TABLE [Log](
[LogId] [BIGINT] IDENTITY(1,1) NOT NULL,
[ServiceInstanceId] [UNIQUEIDENTIFIER] NULL,
[ServiceId] [UNIQUEIDENTIFIER] NOT NULL,
[Component] [NVARCHAR](100) NULL,
[MachineName] [NVARCHAR](50) NULL,
[Datetime] [DATETIME2](3) NOT NULL,
[Severity] [INT] NOT NULL,
[LogText] [NVARCHAR](max) NULL,
[MessageId] [UNIQUEIDENTIFIER] NULL,
[MessageRole] [INT] NULL
) ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [PK_Log] ON [Log]
(
[LogId] ASC,
[datetime] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS=ON)
GO
create TABLE [Log_new1](
[LogId] [BIGINT] IDENTITY(1,1) NOT NULL,
[ServiceInstanceId] [UNIQUEIDENTIFIER] NULL,
[ServiceId] [UNIQUEIDENTIFIER] NOT NULL,
[Component] [NVARCHAR](100) NULL,
[MachineName] [NVARCHAR](50) NULL,
[Datetime] [DATETIME2](3) NOT NULL,
[Severity] [INT] NOT NULL,
[LogText] [NVARCHAR](max) NULL,
[MessageId] [UNIQUEIDENTIFIER] NULL,
[MessageRole] [INT] NULL
) ON PS_Table_Log_Datetime (datetime)
GO
CREATE CLUSTERED INDEX [PK_Log] ON [Log_new1]
(
[LogId] ASC,[Datetime] asc
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
) ON PS_Table_Log_Datetime ([Datetime])
ALTER TABLE [Log] SWITCH TO [Log_new1] PARTITION 5
"I created the same table with same index with partition, but when I
switched the table, SQL Server failed"
This statement isn't consistent with the script. Table Log is not partitioned but Log_new1 is. You need to either partition Log using the same partition scheme or create a check constraint on the Log table datetime column matching the target partition boundaries. The required check constraint definition for the last partition is:
ALTER TABLE Log ADD CONSTRAINT CK_Log_Datetime CHECK (Datetime > '2016-04-08 00:00:00.000');
Related
I know this has been asked before, but none of the answers are fixing the issue, need another set of eyes. I'm trying to create a table and seed it with some values. I don't have any value constraints so I'm not sure why I'm getting the error I'm getting.
CREATE TABLE [dbo].[AvailableTime]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[TimeString] [NCHAR] NOT NULL,
[TimeValue] [NCHAR] NOT NULL,
[CompanyId] [INT] NOT NULL,
[CompanyName] [NVARCHAR](MAX) NULL,
[LocationId] [INT] NOT NULL,
[LocationName] [NVARCHAR] NOT NULL,
[IsClaimed] [BIT] NOT NULL,
CONSTRAINT [PK_AvailableTime]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
INSERT INTO dbo.AvailableTime (TimeString, TimeValue, CompanyId, CompanyName,
LocationId, LocationName, IsClaimed)
VALUES ('2019-01-07T00:00:00', '12:00 AM', 1, 'Company',
2, 'Inver Grove', 'FALSE');
You should never specify a CHAR, VARCHAR, NCHAR or NVARCHAR column (or variable, or parameter) without specifying an explicit length!
If you omit the specific length, in some cases you'll end up with variable or column of exactly ONE character of length! That's typically NOT what you want!
ALSO: why are you storing TimeString and TimeValue as NCHAR?? Doesn't make any sense - use the most appropriate datatype - and here, that would be DATETIME2(n) and TIME.
So define your table like this:
CREATE TABLE [dbo].[AvailableTime]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[TimeString] DATETIM2(0) NOT NULL,
[TimeValue] TIME(0) NOT NULL,
[CompanyId] [INT] NOT NULL,
[CompanyName] [NVARCHAR](MAX) NULL,
[LocationId] [INT] NOT NULL,
[LocationName] [NVARCHAR](100) NOT NULL,
[IsClaimed] [BIT] NOT NULL,
and you should be fine.
You need declare the size of your CHAR & VARCHAR fields in the table:
CREATE TABLE [dbo].[AvailableTime]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[TimeString] [NCHAR](50) NOT NULL,
[TimeValue] [NCHAR](50) NOT NULL,
[CompanyId] [INT] NOT NULL,
[CompanyName] [NVARCHAR](MAX) NULL,
[LocationId] [INT] NOT NULL,
[LocationName] [NVARCHAR](50) NOT NULL,
[IsClaimed] [BIT] NOT NULL,
CONSTRAINT [PK_AvailableTime]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
You have a error in insert query, mismatch types in last column.
INSERT INTO dbo.AvailableTime (TimeString, TimeValue, CompanyId, CompanyName,
LocationId, LocationName, IsClaimed)
VALUES ('2019-01-07T00:00:00', '12:00 AM', 1, 'Company', 2, 'Inver Grove', 0);
I am dealing with a SQL Server on Azure, and I found a rare case where queries over a single table are really slow, over 10 - 12 seconds for a table that has about thousand rows, and while similar tables respond in less that 1 second.
Table definition (script create) is:
CREATE TABLE [dbo].[Content]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Content_ID] [int] NOT NULL,
[CultureCode] [nvarchar](50) NOT NULL,
[Version] [int] NOT NULL,
[UserID] [int] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[Title] [nvarchar](max) NOT NULL,
[Subtitle] [nvarchar](max) NULL,
... 14 more [nvarchar](max) FIELDS...
[NotesPlainText] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.Content]
PRIMARY KEY CLUSTERED ([ID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
)
(the columns Content_ID, CultureCode and Version seem to be a unique combination, even is not set in the table as that. [ID] is just used as row identifier)
Aside of 17 columns all nvarchar(max), nothing else weird.
As I said, no uniques defined, no index ...
So I tune up as
CREATE TABLE [dbo].[Content_optimized]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Content_ID] [int] NOT NULL,
[CultureCode] [nvarchar](50) NOT NULL,
[Version] [int] NOT NULL,
[UserID] [int] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[Title] [nvarchar](max) NOT NULL,
[Subtitle] [nvarchar](max) NULL,
... 14 more [nvarchar](max) FIELDS...
[NotesPlainText] [nvarchar](max) NULL,
)
CREATE INDEX IDX_dbo_Content_optimized__Content_ID
ON [dbo].[Content_optimized]([Content_ID])
CREATE INDEX IDX_dbo_Content_optimized__CultureCode
ON [dbo].[Content_optimized]([CultureCode])
CREATE INDEX IDX_dbo_Content_optimized__Version
ON [dbo].[Content_optimized]([Version])
CREATE INDEX IDX_dbo_Content_optimized__UserID
ON [dbo].[Content_optimized]([UserID])
ALTER INDEX ALL ON [dbo].[Content_optimized] REBUILD WITH (FILLFACTOR=90, ONLINE=ON)
and here where things get weird, I am not saving even a single second of execution.
Indeed code like this:
select *
from [Content]
where Content_ID <> 1049
order by Content_ID, Version
select *
from [Content_optimized]
where Content_ID <> 1049
order by Content_ID, Version
gives a 53% and 47% on the execution plan (just 11% faster because of the INDEXes)
Sure I am relative new to SQL optimisation, so there is something I am not seeing here that may be obvious, but I am right now lost on it.
Any help?
I have two tables as follows where in the later is a table for storing the archived data.
CREATE TABLE [ERP].[Transaction](
[TransactionID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[TransactionDateTime] [datetime] NOT NULL,
[TransactionName] [int] NOT NULL,
[TransactionData] [xml] NOT NULL,
[AcknowledgementDateTime] [datetime] NULL,
[AcknowledgementCode] [int] NULL,
[AcknowledgementDescription] [nvarchar](max) NULL,
[TransactionGUID] [uniqueidentifier] NOT NULL,
[WorkCenter] [nvarchar](10) NULL,
CONSTRAINT [pkTransaction] PRIMARY KEY NONCLUSTERED
(
[TransactionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
GO
ALTER TABLE [ERP].[Transaction] ADD CONSTRAINT [defTransactionTransactionGUID] DEFAULT (newid()) FOR [TransactionGUID]
GO
CREATE TABLE [ERP].[TransactionArchived](
[TransactionID] [int] IDENTITY(1,1) NOT NULL,
[TransactionDateTime] [datetime] NOT NULL,
[TransactionName] [int] NOT NULL,
[TransactionData] [xml] NOT NULL,
[AcknowledgementDateTime] [datetime] NULL,
[AcknowledgementCode] [int] NULL,
[AcknowledgementDescription] [nvarchar](max) NULL,
[TransactionGUID] [uniqueidentifier] NOT NULL,
[WorkCenter] [nvarchar](10) NULL
)
GO
I have made partition as follows and create Indexes to support the partition.
CREATE PARTITION FUNCTION PartitionXFaceDataByMonthPF ( DATETIME )
AS RANGE RIGHT FOR VALUES ( '2010-01-01', '2010-02-01', '2010-03-01', '2010-04-01', '2010-05-01', '2010-06-01', '2010-07-01', '2010-08-01', '2010-09-01', '2010-10-01', '2010-11-01', '2010-12-01',
'2011-01-01', '2011-02-01', '2011-03-01', '2011-04-01', '2011-05-01', '2011-06-01', '2011-07-01', '2011-08-01', '2011-09-01', '2011-10-01', '2011-11-01', '2011-12-01',
'2012-01-01', '2012-02-01', '2012-03-01', '2012-04-01', '2012-05-01', '2012-06-01', '2012-07-01', '2012-08-01', '2012-09-01', '2012-10-01', '2012-11-01', '2012-12-01',
'2013-01-01', '2013-02-01', '2013-03-01', '2013-04-01', '2013-05-01', '2013-06-01', '2013-07-01', '2013-08-01', '2013-09-01', '2013-10-01', '2013-11-01', '2013-12-01',
'2014-01-01', '2014-02-01', '2014-03-01', '2014-04-01', '2014-05-01', '2014-06-01', '2014-07-01', '2014-08-01', '2014-09-01', '2014-10-01', '2014-11-01', '2014-12-01',
'2015-01-01', '2015-02-01', '2015-03-01', '2015-04-01', '2015-05-01', '2015-06-01', '2015-07-01', '2015-08-01', '2015-09-01', '2015-10-01', '2015-11-01', '2015-12-01' ) ;
--Create the PARTITION SCHEME
CREATE PARTITION SCHEME PartitionXFaceDataByMonthPS AS PARTITION PartitionXFaceDataByMonthPF ALL TO ( [PRIMARY] ) ;
Index Creation
ALTER TABLE [ERP].[Transaction] DROP CONSTRAINT [pkTransaction] ;
ALTER TABLE [ERP].[Transaction] ADD CONSTRAINT [pkTransaction] PRIMARY KEY NONCLUSTERED ( [TransactionID] ASC ) ON [PRIMARY] ;
/****** Object: Index [idxTransactionDateTime] Script Date: 01/14/2016 15:53:28 ******/
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[ERP].[Transaction]') AND name = N'idxTransactionDateTime')
DROP INDEX [idxTransactionDateTime] ON [ERP].[Transaction] WITH ( ONLINE = OFF )
GO
CREATE CLUSTERED INDEX idxTransactionDateTime ON [ERP].[Transaction]( [TransactionDateTime] ) ON PartitionXFaceDataByMonthPS( [TransactionDateTime] ) ;
--DROP TABLE [ERP].[TransactionArchived] ; --This needs to execute only if we rerun the same set onace again on the same DB
SELECT * INTO [ERP].[TransactionArchived] FROM [ERP].[Transaction] WHERE 1 = 2 ;
CREATE CLUSTERED INDEX idxTransactionDateTime ON [ERP].[TransactionArchived] ( TransactionDateTime ) ON PartitionXFaceDataByMonthPS( [TransactionDateTime] ) ;
--CREATE NONCLUSTERED INDEX [pkTransaction] ON [ERP].[TransactionArchived] ( [TransactionID] ) ON PartitionXFaceDataByMonthPS( [TransactionDateTime] ) ;
GO
When I am switching data it gives an error as follows which I am struggling to find a solution. Please help
'ALTER TABLE SWITCH' statement failed. The table 'EPMSDataExchange.ERP.Transaction' is partitioned while index 'pkTransaction' is not partitioned.
thanks
pep
I am running into an error on the insertion of a single row into a table, dbo.CFD. The complete error states:
Cannot insert duplicate key row in object 'dbo.CFD' with unique index 'IX_CFD_NRSC_FXTR_N'. The duplicate key value is (BP2001, 1990, CHK, 01, 3456).
Looking at the index in question, IX_CFD_NRSC_FXTR_N, it is a non-unique, non-clustered index on a single column (The column with BP2001 in the error).
Looking at the data, there are many records with the values of BP2001, CHK, 01, and 3456, however none with 1990 (but various other values), so it doesn't seem I am conflicting with a unique constraint.
I also verified that all foreign key constraints are being met and the primary key constraint is not being violated.
How can I figure out what exactly is causing this issue? Every example I can find results in there being duplicate data being inserted, but I don't think that is the issue here. Thanks!
Edit----------
The table create script:
CREATE TABLE [dbo].[CFD](
[PRPSL_I] [int] NOT NULL,
[FILE_TYPE_C] [char](3) NOT NULL,
[CAD_FLR_C] [char](2) NOT NULL,
[FXTR_SERL_I] [int] NOT NULL,
[ADJC_I] [int] NULL,
[CMP_I] [int] NULL,
[VER_I] [int] NULL,
[NRSC_FXTR_N] [varchar](15) NULL,
[MDSE_SPCE_HT_I] [int] NULL,
[MDSE_SPCE_LGTH_I] [int] NULL,
[MDSE_SPCE_DPT_I] [int] NULL,
[NRSC_FXTR_SIDE_I] [int] NULL,
[NRSC_FXTR_SECT_I] [int] NULL,
[BOFM_INCL_F] [bit] NOT NULL,
[DIVI_I] [int] NULL,
[PRTY_I] [int] NULL,
[REUSE_I] [int] NULL,
[FXTR_ISTL_LOC_N] [varchar](6) NULL,
[PHYS_SECT_NUM_I] [int] NULL,
[SAFL_LOC_N] [varchar](4) NULL,
[SEQ_I] [int] NULL,
[SIDE_ASLE_I] [int] NULL,
[LDIN_I] [int] NULL,
[LDIN_STAT_I] [int] NULL,
CONSTRAINT [PK_CFD] PRIMARY KEY CLUSTERED
(
[PRPSL_I] ASC,
[FILE_TYPE_C] ASC,
[CAD_FLR_C] ASC,
[FXTR_SERL_I] ASC
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[CFD] ADD CONSTRAINT [DF_CFD_BOFM_INCL_F] DEFAULT ((0)) FOR [BOFM_INCL_F]
GO
ALTER TABLE [dbo].[CFD] WITH CHECK ADD CONSTRAINT [FK1_CFD] FOREIGN KEY([PRPSL_I], [FILE_TYPE_C], [CAD_FLR_C])
REFERENCES [dbo].[CAD_FILE] ([PRPSL_I], [FILE_TYPE_C], [CAD_FLR_C])
GO
ALTER TABLE [dbo].[CFD] CHECK CONSTRAINT [FK1_CFD]
GO
ALTER TABLE [dbo].[CFD] WITH CHECK ADD CONSTRAINT [FK2_CFD] FOREIGN KEY([CMP_I])
REFERENCES [dbo].[CMP] ([CMP_I])
GO
ALTER TABLE [dbo].[CFD] CHECK CONSTRAINT [FK2_CFD]
GO
ALTER TABLE [dbo].[CFD] WITH CHECK ADD CONSTRAINT [FK3_CFD] FOREIGN KEY([ADJC_I])
REFERENCES [dbo].[ADJC_E] ([ADJC_I])
GO
ALTER TABLE [dbo].[CFD] CHECK CONSTRAINT [FK3_CFD]
GO
ALTER TABLE [dbo].[CFD] WITH CHECK ADD CONSTRAINT [CK_CFD] CHECK (([FILE_TYPE_C]<>'SFP'))
GO
ALTER TABLE [dbo].[CFD] CHECK CONSTRAINT [CK_CFD]
GO
CREATE NONCLUSTERED INDEX [IX_CFD_NRSC_FXTR_N] ON [dbo].[CFD]
(
[NRSC_FXTR_N] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
I have the following query that I am running on my database server but it takes about 30 seconds to run and I can't work out why this is.
SELECT *
FROM [dbo].[PackageInstance] AS packInst
INNER JOIN [dbo].[PackageDefinition] AS packageDef
ON packInst.[PackageDefinitionID] = packageDef.[PackageDefinitionID]
LEFT OUTER JOIN [dbo].[PackageInstanceContextDef] AS contextDef
ON packInst.[PackageInstanceID] = contextDef.[PackageInstanceID]
This produced the following execution plan which to me looks to be good....so I can't understand why it takes so much time to execute where the resulting data is only 100,000 records (which should be a walk in the park for SQL Server).
Any ideas what could be causing this long execution time?
I have looked at the query in Profiler to see what the stats where on it and they are as follows:
CPU - 4711
Reads - 744453
Writes - 9
Duration - 26329
The following are the table definitions:
CREATE TABLE [dbo].[PackageDefinition](
[PackageDefinitionID] [int] IDENTITY(1,1) NOT NULL,
[ts] [timestamp] NOT NULL,
[ProgramID] [int] NULL,
[VendorID] [int] NULL,
[PackageExecutionTypeID] [int] NULL,
[PackageDefinitionStatusID] [int] NOT NULL,
[IsInternal] [bit] NOT NULL,
[Name] [dbo].[D_Name] NOT NULL,
[Description] [dbo].[D_Description] NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[PublishedDate] [datetime] NULL,
[OwnerUserGuid] [uniqueidentifier] NOT NULL,
[ProcessDefinitionMainID] [int] NULL,
[KeyInfoHtml] [nvarchar](max) NULL,
[DescriptionHtml] [nvarchar](max) NULL,
[WhatToExpectHtml] [nvarchar](max) NULL,
[BestPracticesHtml] [nvarchar](max) NULL,
[RecommendedJourneysHtml] [nvarchar](max) NULL,
[RequiresSLAAgreement] [bit] NOT NULL,
[SLAFileAssetID] [int] NULL,
[ImageDataID] [int] NULL,
[VideoHtml] [nvarchar](max) NULL,
[VideoAssetID] [int] NULL,
[UseMapCosts] [bit] NOT NULL,
[CostMin] [money] NOT NULL,
[CostMax] [money] NOT NULL,
[LandingPageVisitCount] [int] NOT NULL,
[IsDeleted] [dbo].[D_IsDeleted] NOT NULL,
[CreatedByUserGuid] [uniqueidentifier] NOT NULL,
[OrderHtml] [nvarchar](max) NULL,
CONSTRAINT [PK_PackageDefinition] PRIMARY KEY CLUSTERED
(
[PackageDefinitionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[PackageInstance](
[PackageInstanceID] [int] IDENTITY(1,1) NOT NULL,
[ts] [timestamp] NOT NULL,
[PackageDefinitionID] [int] NOT NULL,
[PackageStatusID] [int] NOT NULL,
[Name] [dbo].[D_Description] NOT NULL,
[CampaignID] [int] NULL,
[MarketingPlanID] [int] NULL,
[CountryID] [int] NULL,
[DateEntered] [datetime] NULL,
[DateExecuted] [datetime] NULL,
[ProcessID] [int] NULL,
[OrderedByUserGuid] [uniqueidentifier] NULL,
[RequestedByUserGuid] [uniqueidentifier] NULL,
[SLAEndDate] [datetime] NULL,
CONSTRAINT [PK_PackageInstance] PRIMARY KEY CLUSTERED
(
[PackageInstanceID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[PackageInstanceContextDef](
[PackageInstanceContextDefID] [int] IDENTITY(1,1) NOT NULL,
[ts] [timestamp] NOT NULL,
[PackageInstanceID] [int] NOT NULL,
[ContextObjectDefID] [int] NOT NULL,
[EnteredFieldValue] [varchar](max) NULL,
[SelectedListValueID] [int] NULL,
[AssetIdsString] [nvarchar](max) NULL,
[SelectedListValueIdsString] [nvarchar](max) NULL,
[ContextObjectFieldName] [nvarchar](30) NOT NULL,
CONSTRAINT [PK_PackageInstanceContextDef] PRIMARY KEY CLUSTERED
(
[PackageInstanceContextDefID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Remove the * in SELECT *
It will always scan because you ask for all columns. And do you have clustered indexes?
The answer turned out to be what #MartinSmith suggested. Because the PackageDefinition table contained about 8 NVARCHAR(MAX) columns, when the resulting join was created and that was over 100k rows, this was causing the varchar(max) values to be re-read over and over and they exist in out of row pages. Hence the large number of logical reads.
Thanks all for your support, just have to figure out to make the entity framework produce the query that I want.
What happens if you add the following index...
CREATE NONCLUSTERED INDEX ix ON PackageDefinition(PackageDefinitionID)
...and try the following to reduce the width of the data going into the sort?
SELECT packInst.*,
packageDef2.*,
contextDef.*
FROM [dbo].[PackageInstance] AS packInst
INNER MERGE JOIN [dbo].[PackageDefinition] AS packageDef
ON packInst.[PackageDefinitionID] = packageDef.[PackageDefinitionID]
LEFT OUTER MERGE JOIN [dbo].[PackageInstanceContextDef] AS contextDef
ON packInst.[PackageInstanceID] = contextDef.[PackageInstanceID]
INNER MERGE JOIN [dbo].[PackageDefinition] AS packageDef2
ON packageDef.[PackageDefinitionID] = packageDef2.[PackageDefinitionID]
OF course * should not be used as even if you need all columns you definitely won't need the same columns twice as the result of the JOIN but this is just to maintain the semantics of your original query.