Производительность SQL Server 2005 CTE много логических чтений - PullRequest
1 голос
/ 12 декабря 2011

У меня есть запрос CTE, который, кажется, вызывает очень много логических чтений (или, возможно, это не так). Я запустил трассировки SQL Server Profiler, и этот запрос, по-видимому, постоянно вызывает один из самых длительных запросов. (он вызывается при каждом нажатии страницы)

По сути, я хочу знать, правильно ли оптимизирован мой CTE или его можно улучшить.

SET STATISTICS IO ON;
GO
    ;WITH cte (PageId, PageTitle, PageType, PageHeadingId, ParentPage, InNavigation, OrgLevel, SortKey, PageOrder, PathLength, PathName, Active) AS
     (
      SELECT
        PageId, 
        PageTitle,
        PageType,
        PageHeadingId,
        ParentPage, 
        InNavigation,
        0, 
        CAST (PageOrder  AS VARBINARY(200)), 
        PageOrder, 
        0 AS PathLength, 
        CAST('' as varchar(300)) AS PathName,
        Active
       FROM dbo.ContentPage
       WHERE ParentPage = 0
        AND InNavigation = 1
      UNION ALL
      SELECT
        b.PageId, 
        b.PageTitle, 
        b.PageType,
        b.PageHeadingId,
        b.ParentPage,
        b.InNavigation, 
        cte.OrgLevel+1,
        CAST(cte.SortKey + CAST (b.PageOrder AS BINARY(4)) AS VARBINARY(200)),
        b.PageOrder, 
        ((cte.OrgLevel+1) + len('....'+b.PageTitle)) as PathLength,
        CAST ((cte.PathName+'....') AS VARCHAR(300)) AS PathName,
        b.Active
       FROM dbo.ContentPage b
         JOIN cte ON b.ParentPage = cte.PageId
       WHERE b.PageType NOT IN (4, 8, 11, 12, 14)
        -- Remove specific page types from the ContentPage table
     )
    SELECT *, (PathName+PageTitle) AS Hierarchy 
    FROM cte WHERE InNavigation = 1     
    ORDER BY SortKey--, PageOrder
SET STATISTICS IO OFF;
GO

Если я оставлю эту строку:

WHERE b.PageType NOT IN (4, 8, 11, 12, 14)

, то количество логических чтений увеличивается с ~ 8500 до ~ 13000

(что делает запрос, это строит иерархию выпадающего меню в ASP.NET). Если с логическим чтением все в порядке, то я предполагаю, что мне придется придумать другой способ кэширования / сохранения этого меню (которое получает обновляется 2 или 3 раза в неделю)

спасибо

Структура таблицы для ContentPage

CREATE TABLE [dbo].[ContentPage](
    [PageId] [int] IDENTITY(1,1) NOT NULL,
    [PageTitle] [nvarchar](150) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [PageQuote] [nvarchar](400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [MetaKeywords] [nvarchar](200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [MetaDescription] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [PageContent] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Active] [bit] NOT NULL CONSTRAINT [DF_ContentPage_Active]  DEFAULT ((0)),
    [InNavigation] [bit] NOT NULL CONSTRAINT [DF_ContentPage_InNavigation]  DEFAULT ((1)),
    [PageOrder] [int] NOT NULL CONSTRAINT [DF_ContentPage_PageOrder]  DEFAULT ((50)),
    [ParentPage] [int] NOT NULL CONSTRAINT [DF_ContentPage_ParentPage]  DEFAULT ((0)),
    [PageType] [int] NOT NULL CONSTRAINT [DF_ContentPage_PageType]  DEFAULT ((1)),
    [CreatedBy] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [CreatedOn] [datetime] NULL,
    [ModifiedBy] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [ModifiedOn] [datetime] NULL,
    [PageViews] [int] NOT NULL CONSTRAINT [DF_ContentPage_PageViews]  DEFAULT ((0)),
    [Emailed] [int] NOT NULL CONSTRAINT [DF_ContentPage_Emailed]  DEFAULT ((0)),
    [Emailable] [bit] NOT NULL CONSTRAINT [DF_ContentPage_Emailable]  DEFAULT ((1)),
    [Printable] [bit] NOT NULL CONSTRAINT [DF_ContentPage_Printable]  DEFAULT ((1)),
    [ContactButton] [bit] NOT NULL CONSTRAINT [DF_ContentPage_PDFable]  DEFAULT ((0)),
    [PageHeadingId] [int] NULL CONSTRAINT [DF_ContentPage_PadeHeadingId]  DEFAULT ((0)),
    [AlternativeTitle] [nvarchar](150) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [RighthandImage] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [IsMicrosite] [bit] NOT NULL CONSTRAINT [DF_ContentPage_IsMicrosite]  DEFAULT ((0)),
 CONSTRAINT [PK_ContentPage] PRIMARY KEY CLUSTERED 
(
    [PageId] 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]

1 Ответ

0 голосов
/ 12 декабря 2011

Ваш CTE использует внутреннее JOIN обратно к себе, поэтому здесь есть отношение внешнего ключа:

FROM dbo.ContentPage b
JOIN cte ON b.ParentPage = cte.PageId

Таким образом, наличие индекса на b.ParentPage и еще одного на PageId может быть полезным.

Кроме того, в вашем запросе есть WHERE предложений для b.PageType и InNavigation, поэтому следует учитывать индекс для PageType (или, возможно, (PageType, InNavigation) вместе взятых).

Кроме того, вы сортируете по SortKey, который основан на PageOrder, поэтому индекс по нему также может быть полезен.

Попробуйте создать по одному индексу за раз, повторите запрос, сравните статистику и цифры, а затем решите, какие из них действительно вам полезны (а какие нет). Индексирование не является точной наукой - вы не всегда можете предсказать, что помогает и работает, а что нет - вы должны попробовать это и сравнить с исходным запросом, а затем решить, что помогает, а что нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...