首先按 Id 然后按日期时间选择行 - 有或没有子查询?
Selecting rows first by Id then by datetime - with or without a subquery?
我需要从多个日志 table 中创建统计信息。大部分时间每小时一次,但有时更频繁地每 5 分钟一次。
仅通过 datetime
选择行对于较大的日志来说不够快,所以我想我 select 通过存储最大 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 服务器是否足够智能:
- 首先按
Id
过滤行,然后按 Timestamp
过滤行,即使我更改了条件的顺序或条件顺序是否重要或
- 我是否需要一个子查询来首先 select 按
Id
的行然后按 Timestamp
. 过滤它们
带有子查询:
SELECT *
FROM (
SELECT TOP(1000) * FROM [dbo].[Log]
WHERE Id > lastId
ORDER BY [Id] DESC
) t
WHERE t.[TimeStamp] >= timestampMin
table 架构是:
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]
我试图使用查询计划来了解它是如何工作的,但事实证明我看不懂它,也不理解它。
在您的情况下,您在 TimeStamp
上没有索引,因此 SQL 服务器将始终首先使用聚簇索引 (Id
)(您在中看到的聚簇索引查找查询计划)找到匹配 Id > lastId
和 的第一行,然后 使用谓词 [Timestamp] >= timestampMin
对剩余行执行扫描(实际上是相反的方式,因为您正在使用 DESC
以相反的顺序排序)。
如果您要在 TimeStamp
SQL 服务器上添加索引 可能 使用它基于:
谓词的基数 [Timestamp] >= timestampMin
。请注意,基数始终是基于统计数据的估计值(参见 https://msdn.microsoft.com/en-us/library/ms190397.aspx) and the cardinality estimator (it changed from SQL 2012 to 2014+, see https://msdn.microsoft.com/en-us/library/dn600374.aspx)。
如何覆盖非聚集索引(因为您使用的是通配符,所以无论如何都无关紧要)。如果非聚集索引不覆盖 SQL 服务器必须添加一个 Key Lookup
(请参阅 https://technet.microsoft.com/en-us/library/bb326635(v=sql.105).aspx)运算符以检索所有字段(或执行连接)。这可能会使索引不适合此查询。
另请注意,您的两个查询(一个有子计划,一个没有)在功能上是不同的。第一个会给你前 1000 行有 both Id > lastId AND [Timestamp] >= timestampMin
。第二个将只为您提供具有 Id > lastId
的前 1000 行中具有 [Timestamp] >= timestampMin
的行。因此,例如,您可能从第一个查询中获得 1000 行,但比第二个查询中的少。
我需要从多个日志 table 中创建统计信息。大部分时间每小时一次,但有时更频繁地每 5 分钟一次。
仅通过 datetime
选择行对于较大的日志来说不够快,所以我想我 select 通过存储最大 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 服务器是否足够智能:
- 首先按
Id
过滤行,然后按Timestamp
过滤行,即使我更改了条件的顺序或条件顺序是否重要或 - 我是否需要一个子查询来首先 select 按
Id
的行然后按Timestamp
. 过滤它们
带有子查询:
SELECT *
FROM (
SELECT TOP(1000) * FROM [dbo].[Log]
WHERE Id > lastId
ORDER BY [Id] DESC
) t
WHERE t.[TimeStamp] >= timestampMin
table 架构是:
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]
我试图使用查询计划来了解它是如何工作的,但事实证明我看不懂它,也不理解它。
在您的情况下,您在 TimeStamp
上没有索引,因此 SQL 服务器将始终首先使用聚簇索引 (Id
)(您在中看到的聚簇索引查找查询计划)找到匹配 Id > lastId
和 的第一行,然后 使用谓词 [Timestamp] >= timestampMin
对剩余行执行扫描(实际上是相反的方式,因为您正在使用 DESC
以相反的顺序排序)。
如果您要在 TimeStamp
SQL 服务器上添加索引 可能 使用它基于:
谓词的基数
[Timestamp] >= timestampMin
。请注意,基数始终是基于统计数据的估计值(参见 https://msdn.microsoft.com/en-us/library/ms190397.aspx) and the cardinality estimator (it changed from SQL 2012 to 2014+, see https://msdn.microsoft.com/en-us/library/dn600374.aspx)。如何覆盖非聚集索引(因为您使用的是通配符,所以无论如何都无关紧要)。如果非聚集索引不覆盖 SQL 服务器必须添加一个
Key Lookup
(请参阅 https://technet.microsoft.com/en-us/library/bb326635(v=sql.105).aspx)运算符以检索所有字段(或执行连接)。这可能会使索引不适合此查询。
另请注意,您的两个查询(一个有子计划,一个没有)在功能上是不同的。第一个会给你前 1000 行有 both Id > lastId AND [Timestamp] >= timestampMin
。第二个将只为您提供具有 Id > lastId
的前 1000 行中具有 [Timestamp] >= timestampMin
的行。因此,例如,您可能从第一个查询中获得 1000 行,但比第二个查询中的少。