【问题标题】:Performance regarding selecting last n records from a table关于从表中选择最后 n 条记录的性能
【发布时间】:2012-04-25 19:17:58
【问题描述】:

我正在查询表以选择最后 n 条记录但保留顺序。为此,我使用了从Select Top N Records Ordered by X, But Have Results in Reverse Order 获得的以下查询:

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

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

正如您所看到的,除了内部查询之外,索引正在跟踪,并且您可以在索引计划中看到 77% 的执行由排序过程完成。 我怎样才能避免这种情况?我应该在这里应用什么索引来克服这种情况。

【问题讨论】:

  • 是的,确实如此。但是我可以更改我的查询或创建一些不同的索引来为这 10 条记录应用索引吗?
  • 查看我的回答,解决该问题。

标签: sql sql-server sql-server-2005 indexing


【解决方案1】:

占用执行计划 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 条记录进行排序)占用了大部分执行时间,那么我会说您状态良好。

【讨论】:

  • 我想克服那个排序运算符也可能为那个运算符应用一些索引?
  • @RockySingh 关键是您不能将所有操作减少到 0%。这项工作必须在某个地方完成。由于您的排序是在物化表(CTE)上,我不知道可以使用索引。即便如此,它也仅适用于 10 行。这将真正缩短执行时间多少?
  • 实际上数字始终是 100%。它本身并不是“昂贵的”,而是“在那里花费了多少时间”。如果你减少索引搜索 - 你认为 100% 去哪里 - 其他地方。它必须足够快,并且花费的时间必须有意义。在这里 - 通过索引访问数据。但数字总是以 100 结尾 - 这是相对重量,而不是绝对重量。
猜你喜欢
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多