我想调整这个查询 - 它正在读取比我想要的更多的行。我已按照 Database Tuning Advisor 的建议添加了一个索引。
查询是这样的:
SET STATISTICS TIME, IO ON;
SELECT TOP 1000 project,
Max(timestamp) timestamp
FROM the_table
WHERE deviceid = 581
GROUP BY project
IO ,时间统计是这样的:
Table 'the_table'. Scan count 1, logical reads 2373, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 390 ms, elapsed time = 829 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
执行计划可以在这里找到。
此查询查找的 dta_index 由projectnumber
和组成timestamp
。该表大约有 4,500,000 行,消耗大约 350MB,每条deviceid
记录的数量大致相同(即均匀分布,每个设备大约有 700K 条记录)。
我的问题:即使我只请求表中的前 1,000 行,无论我创建了什么索引或如何尝试重新编写查询,我总是最终读取 +/- 700K 行(即所有WHERE
子句中所选设备的行)。如果您能放弃有关如何调整此查询的提示,我将不胜感激。
我不认为有比接触大约 700K 行更快的方法来缩小这个查询,特别是deviceid
使用 exec 的第一个运算符。计划。
这是一个最小的可重现示例,包括表定义和两个示例行的插入:
CREATE TABLE [dbo].[the_table]
(
[primary_key_col] [int] IDENTITY(1,1) NOT NULL,
[Project] [int] NULL,
[DeviceID] [int] NULL,
[TimeStamp] [datetime] NULL,
[Quantity] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[primary_key_col] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
SET IDENTITY_INSERT [dbo].[the_table] ON;
INSERT [dbo].[the_table] ([primary_key_col], [Project], [DeviceID], [TimeStamp], [Quantity]) VALUES (4825107, 1232, 587, CAST(N'2021-10-23T05:48:48.000' AS DateTime), 1);
INSERT [dbo].[the_table] ([primary_key_col], [Project], [DeviceID], [TimeStamp], [Quantity]) VALUES (4825108, 6458, 581, CAST(N'2021-10-23T05:49:17.000' AS DateTime), 1);
primary_key_col | 项目 | 设备ID | 时间戳 | 数量 |
---|---|---|---|---|
4825107 | 1232 | 587 | 2021-10-23 05:48:48.000 | 1 |
4825108 | 6458 | 581 | 2021-10-23 05:49:17.000 | 1 |
索引不是故意的问题的一部分,无论我尝试了哪个索引,对于特定的 deviceID,我总是达到 700K 行。
谢谢。
“我的问题:即使我只读取表中的前 1000 行”你不是。您正在阅读分组查询的前 1000 个结果(没有任何排序) -
top 1000
在处理顺序中排在最后。如果您想获取与
deviceid
谓词匹配的“随机”1000 行,则可以使用子查询:抱歉,但从我的角度来看,您应该重新考虑您的查询逻辑,因为它会获取所有匹配的行
deviceid
并从匹配的行中获取前 1000 个,而不是从表中获取前 1000 个。你也可以在你的执行计划中看到它:右侧是一个表查找deviceid
,TOP 是左侧的最后一个运算符。这就是你得到这么多行的原因。