我正在查询表以选择最后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%的执行。 如何避免这种情况?我应该在这里应用什么索引来克服这种情况。
答案 0 :(得分: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条记录)占用了大部分执行时间,那么我会说你处于良好的状态。