2016-12-01 39 views
1

我需要从几个日志表中创建统计信息。每小时大部分时间,但有时每5分钟更频繁一次。先选择行,然后按日期时间 - 有没有子查询?

选择行只有datetime不是更大的日志速度不够快,所以我想我只选择通过存储最大Id,下次再使用它是自上次查询新行:

SELECT TOP(1000) * -- so that it's not too much 
FROM [dbo].[Log] 
WHERE Id > lastId AND [Timestamp] >= timestampMin 
ORDER BY [Id] DESC 

select1

我的问题:在SQL Server足够聪明到:

  • 第一滤波器由行10,然后是Timestamp,即使我更改条件的顺序或条件顺序是否重要,或者
  • 是否需要子查询先按Id选择行,然后再通过Timestamp筛选它们。

与子查询:

SELECT * 
FROM (
    SELECT TOP(1000) * FROM [dbo].[Log] 
    WHERE Id > lastId 
    ORDER BY [Id] DESC 
) t 
WHERE t.[TimeStamp] >= timestampMin 

select2

表架构是:

CREATE TABLE [dbo].[Log](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Timestamp] [datetime2](7) NOT NULL, 
    -- other columns  
CONSTRAINT [PK_dbo_Log] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

我试图使用查询计划,以找出它是如何工作的,但事实证明我无法阅读,但我不明白。

+0

条件的顺序并不重要,引擎会列出使用它们的最佳方式。你的子查询返回的结果与原来的结果不同,原因在于你里面的“TOP 1000”。那是你要的吗?我认为'TOP 1000'应该在外部查询中。 – NickyvV

+0

大多数情况下,如果您问:“SQL Server足够聪明......”答案通常是肯定的。 – Tanner

+0

@NickyvV现在你提到了'TOP 1000'我认为你是对的。如果我把它放在内部查询中,结果可能会不同。 – t3chb0t

回答

1

你的情况,你不必这么TimeStamp SQL Server上的索引将始终使用聚集索引(Id)(第聚集索引寻求在查询计划中看到)找到第一行匹配Id > lastId然后使用谓词[Timestamp] >= timestampMin对其余行执行扫描(实际上是其他方法,因为您按与DESC相反的顺序排序)。

如果你对TimeStamp SQL添加索引服务器可能使用它的基础上:

  1. 谓语[Timestamp] >= timestampMin的基数。请注意,基数总是基于统计信息(请参见https://msdn.microsoft.com/en-us/library/ms190397.aspx)和基数估计器(它从SQL 2012更改为2014+,请参阅https://msdn.microsoft.com/en-us/library/dn600374.aspx)的估计值。

  2. 如何覆盖非聚集索引(因为你使用的是通配符,它​​无论如何不会有问题)。如果非聚集索引不覆盖,SQL Server将不得不添加一个Key Lookup(请参见https://technet.microsoft.com/en-us/library/bb326635(v=sql.105).aspx)运算符以检索所有字段(或执行联接)。这可能会使索引不值得这个查询。

另请注意,您的两个查询 - 一个与子计划和一个没有 - 在功能上是不同的。首先会给你前1000行Id > lastId AND [Timestamp] >= timestampMin。第二个将只给你从Id > lastId前1000行的[Timestamp] >= timestampMin行。因此,例如,您可能会从第一个查询中获得1000行,但比第二个查询少。

相关问题