2012-04-13 214 views
1

我正在查询表以选择最后n条记录,但保留了顺序。对于这一点,我使用下面的查询这是我从Select Top N Records Ordered by X, But Have Results in Reverse Order有:关于从表中选择最后n条记录的性能

WITH Temp 
      AS (SELECT TOP 10 
         [TestID] , 
         UserID , 
         DateSent 
       FROM  [Test] 
       WHERE UserID = @UserID 
       ORDER BY DateSent DESC 
      ) 
    SELECT * 
    FROM Temp 
    ORDER BY DateSent 

即我选择最后N条记录,同时保留排序顺序。下面是空的脚本创建上述表:

GO 
CREATE TABLE [dbo].[Test] 
    (
     [TestID] [int] IDENTITY(1, 1) 
        NOT NULL , 
     [UserID] [int] NOT NULL , 
     [DateSent] [datetime] NOT NULL , 
     CONSTRAINT [PK_TestID] PRIMARY KEY CLUSTERED ([TestID] ASC) 
     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
       ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) 
ON [PRIMARY] 
GO 

CREATE NONCLUSTERED INDEX [IX_Test_UserID_DateSent] ON [dbo].[Test] 
(
    [UserID] ASC, 
    DateSent DESC 
)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 


GO 

INSERT INTO [Test] 
SELECT TOP 100000 ABS(CAST(NEWID() AS BINARY(6)) %10), 
DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 1 - FLOOR(RAND(CAST(NEWID() AS binary(4))) * 365.25 * 90), 0) 
FROM master..spt_values 
GO 

我在上文中创建的表,就可以申请指数,并在其中插入一些虚拟的数据。我执行此查询来获取记录:

DECLARE @UserID INT 
SET @UserID = 1 ; 
WITH Temp 
      AS (SELECT TOP 10 
         [TestID] , 
         UserID , 
         DateSent 
       FROM  [Test] 
       WHERE UserID = @UserID 
       ORDER BY DateSent DESC 
      ) 
    SELECT * 
    FROM Temp 
    ORDER BY DateSent 

下面是运行上面的查询后的执行计划:

enter image description here

正如你可以看到指数以下,但对于内部查询和您可以在索引计划中看到77%的执行是由排序过程执行的。 我该如何避免这种情况?我应该在这里应用什么指数来克服这种情况。

+0

是的的确的。但是,我可以更改我的查询或创建一些不同的索引来为这10条记录应用索引吗? – 2012-04-13 12:19:18

+0

查看我的回答哪个地址的问题。 – Yuck 2012-04-13 12:21:22

回答

5

消耗77%执行计划的最左侧排序仅适用于您的TOP 10记录。您可以通过删除最后ORDER BY验证这一点:

DECLARE @UserID INT 
SET @UserID = 1 ; 
WITH Temp 
      AS (SELECT TOP 10 
         [TestID] , 
         UserID , 
         DateSent 
       FROM  [Test] 
       WHERE UserID = @UserID 
       ORDER BY DateSent DESC 
      ) 
    SELECT * 
    FROM Temp 
    --ORDER BY DateSent 

应当提及的是,在一个计划中的所有运营商必须为100%。如果您最便宜的操作(即仅分类10条记录)消耗大部分执行时间,那么我会说您状态良好。

enter image description here

+0

我想要克服那个Sort Operator也可能为该操作符应用一些索引呢? – 2012-04-13 12:27:16

+0

@RockySingh问题是你不能将所有操作减少到0%。这项工作必须在某个地方完成。由于你的排序是在物化表(CTE)上,我不知道索引是否可以使用。即使如此,它仅适用于** 10行**。这会真正提高执行时间多少? – Yuck 2012-04-13 12:32:59

+0

其实nubmers总是100%。它本身并不是“昂贵的”,而是“在那里花费了多少时间”。如果你减少索引寻求 - 你认为100%去哪里 - 在别的地方。它必须足够快,花时间花在时间上必须合理。它在这里 - 通过索引访问数据。但这些数字总是最终为100--这是相对的重量,而不是绝对的。 – TomTom 2012-04-13 13:23:56

相关问题