Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 先按Id选择行,然后按日期时间选择行-是否有子查询?_Sql Server_Tsql_Datetime_Database Performance - Fatal编程技术网

Sql server 先按Id选择行,然后按日期时间选择行-是否有子查询?

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

我需要从几个日志表中创建统计信息。大部分时间是每小时一次,但有时更频繁的是每5分钟一次

仅按
datetime
选择行对于较大的日志来说不够快,因此我认为我只选择自上次查询以来新的行,方法是存储max
Id
并在下次重新使用它:

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
    ,我想你是对的。如果我把它放在内部查询中,结果可能会不同。