Sql server 先按Id选择行,然后按日期时间选择行-是否有子查询?
我需要从几个日志表中创建统计信息。大部分时间是每小时一次,但有时更频繁的是每5分钟一次 仅按Sql server 先按Id选择行,然后按日期时间选择行-是否有子查询?,sql-server,tsql,datetime,database-performance,Sql Server,Tsql,Datetime,Database Performance,我需要从几个日志表中创建统计信息。大部分时间是每小时一次,但有时更频繁的是每5分钟一次 仅按datetime选择行对于较大的日志来说不够快,因此我认为我只选择自上次查询以来新的行,方法是存储maxId并在下次重新使用它: SELECT TOP(1000) * -- so that it's not too much FROM [dbo].[Log] WHERE Id > lastId AND [Timestamp] >= timestampMin ORDER BY [Id] DESC
datetime
选择行对于较大的日志来说不够快,因此我认为我只选择自上次查询以来新的行,方法是存储maxId
并在下次重新使用它:
SELECT TOP(1000) * -- so that it's not too much
FROM [dbo].[Log]
WHERE Id > lastId AND [Timestamp] >= timestampMin
ORDER BY [Id] DESC
我的问题:SQL Server是否足够智能,可以:
- 首先按
过滤行,然后按Id
过滤行,即使我更改了条件的顺序,或者条件顺序是否重要时间戳
- 我是否需要一个子查询来首先按
选择行,然后按Id
时间戳过滤它们
SELECT *
FROM (
SELECT TOP(1000) * FROM [dbo].[Log]
WHERE Id > lastId
ORDER BY [Id] DESC
) t
WHERE t.[TimeStamp] >= timestampMin
表架构为:
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]
我试图使用查询计划来了解它是如何工作的,但结果是我无法阅读它,也不理解它。在您的情况下,
时间戳上没有索引,因此SQL Server将始终首先使用聚集索引(Id
)(聚集索引在查询计划中查找)查找与Id>lastId
匹配的第一行,然后使用谓词[Timestamp]>=timestamin
对其余行执行扫描(实际上是另一种方式,因为您是按与DESC
相反的顺序排序的)
如果要在时间戳上添加索引,SQL Server可能会基于以下内容使用它:
谓词的基数[Timestamp]>=timestampMin
。请注意,基数始终是基于统计(请参阅)和基数估计器(它从SQL 2012更改为2014+,请参阅)的估计
覆盖非聚集索引的程度如何(因为您使用的是通配符,所以无论如何都无关紧要)。如果非聚集索引是非覆盖索引,SQL Server必须添加一个键查找
(请参阅)运算符,以便检索所有字段(或执行联接)。这可能会使索引不值得用于此查询
还要注意的是,您的两个查询(带子计划的查询和不带子计划的查询)在功能上是不同的。第一个将为您提供前1000行,其中既有Id>lastId,又有[Timestamp]>=timestampMin
。第二个将只提供前1000行中具有Id>lastId
的行中具有[Timestamp]>=timestampMin
。因此,例如,您可能从第一个查询中获得1000行,但比第二个查询中的行少 条件的顺序无关紧要,引擎会找出使用它们的最佳方式。您的子查询返回的结果与原始结果不同,这是因为您的TOP1000
在其中。这就是你想要的吗?我认为TOP1000
应该在外部查询中。大多数情况下,如果你问:“SQL Server够聪明吗…”,答案通常是肯定的。@NickyvV既然你提到了TOP1000
,我想你是对的。如果我把它放在内部查询中,结果可能会不同。