1

我有一个CTE查询似乎造成了很多逻辑读取(或者它可能不)。我已经运行SQL Server Profiler跟踪,并且此查询似乎一直导致运行时间最长的查询之一。 (它确实每个页面命中调用)SQL Server 2005 CTE性能大量的逻辑读取

基本上我想知道我的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] 
+0

一些表格说明:ContentPage包含529行并占用2.8Mb,CTE返回约54行数据。 – kolin

+0

这些表是什么样的(结构,列和数据类型)?什么样的指数到位? –

+1

你有什么样的指数? WHERE子句中使用的列和外键列索引? –

回答

0

你的CTE使用内部JOIN回到自己 - 所以有几分的外键关系在这里:

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

因此,有上b.ParentPage指数另一个在PageId可能会有所帮助。

此外,查询对b.PageTypeInNavigationWHERE条款,所以你应该考虑PageType(或可能(PageType, InNavigation)组合)的索引。

此外,你排序SortKey这是基于PageOrder所以一个索引可能也是有用的。

尝试一次创建一个索引,重新运行查询,比较您的统计数字和数字 - 然后确定哪些对您真正有益(哪些不会)。索引不是一门精确的科学 - 你不能总是预测什么是有用的,什么不可行 - 你必须尝试一下,并与原始查询进行比较,然后确定哪些有用,哪些不用。

+0

感谢marc,我已经尝试了几个不同的索引,并将逻辑读取从4553减少到3297,(PageId(聚集索引)的碎片也是59%。我会继续尝试一些建议 – kolin

+0

我'我将它标记为已回答,因为索引似乎已经改善了性能,并且我也申请了很多其他表格。 – kolin