Почему это соединение занимает так много времени? - PullRequest
2 голосов
/ 14 октября 2011

У меня есть следующий запрос, который я выполняю на своем сервере баз данных, но для его выполнения требуется 30 секунд , и я не могу понять, почему это так.

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]

Это привело к следующему плану выполнения, который для меня выглядит хорошим ... поэтому я не могу понять, почему требуется так много времени для выполнения, где результирующие данные составляют только 100 000 записей (что должно быть прогулкой в парк для SQL Server).

SQL Server Execution Plan

Есть идеи, что может быть причиной этого долгого времени выполнения?

Я посмотрел на запрос в Профилировщике, чтобы увидеть, какие статистические данные находятся на нем, и они выглядят следующим образом:

CPU - 4711
Reads - 744453
Writes - 9
Duration - 26329

Ниже приведены определения таблиц:

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]

Ответы [ 3 ]

2 голосов
/ 20 октября 2011

Ответ оказался тем, что предложил @MartinSmith. Поскольку таблица PackageDefinition содержала около 8 столбцов NVARCHAR (MAX), при создании результирующего объединения, в котором было более 100 тыс. Строк, это вызывало многократное чтение значений varchar (max) и их существование вне строки страницы. Отсюда большое количество логических операций чтения.

Спасибо всем за вашу поддержку, просто нужно выяснить, чтобы структура сущностей создала запрос, который я хочу.

2 голосов
/ 14 октября 2011

Удалить * in SELECT *

Он всегда будет сканировать, потому что вы просите все столбцы. А у вас есть кластерные индексы?

0 голосов
/ 14 октября 2011

Что произойдет, если вы добавите следующий индекс ...

CREATE NONCLUSTERED INDEX ix ON  PackageDefinition(PackageDefinitionID)

... и попробуйте следующее, чтобы уменьшить ширину данных, входящих в сортировку?

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]  

Конечно * не следует использовать, так как даже если вам нужны все столбцы, вам точно не понадобятся одинаковые столбцы дважды в результате JOIN, но это просто для того, чтобы поддерживать семантику вашего исходного запроса.

...