我正在开发一个查询,以针对包含时间序列中一堆点的表进行查询。该表可以增长得相当大,所以我希望查询通过在固定的时间间隔内平均点来有效地对输出进行下采样。在编写查询之后,我对SQL Server(2008)如何选择执行查询感到惊讶。执行计划揭示了一种不必要的排序操作,随着时间序列的增长,这种操作将变得非常昂贵这是问题所在,降低到一个简单的例子:集合分组单调函数的冗余分类
CREATE TABLE [dbo].[Example]
(
[x] FLOAT NOT NULL,
[y] FLOAT NOT NULL,
PRIMARY KEY CLUSTERED
(
[x] ASC
)
);
SELECT FLOOR([x]), AVG([y])
FROM [dbo].[Example]
GROUP BY FLOOR([x]);
在这里,我(X,Y),它们已经用x排序(因为聚集主键的)对,并且我对每个平均ÿ整数x(通过截断FLOOR
函数)。我希望表格已经适当地排序,因为FLOOR
是一个单调函数。不幸的是,SQL Server会需要这些数据重新排序,这里是执行计划:
不宜SQL服务器能够在一个单调功能分组数据进行流聚集已经适当排序的列?
是否有一种通用的方法来重写这样的查询,以便SQL Server能够看到命令被保留下来?
[更新] 我发现关于这个问题Things SQL needs: sargability of monotonic functions的文章,正如标题所暗示的,好像这是一个优化的SQL Server目前还不做(在大多数情况下)。
这里有超过[dbo].[Example]
甚至更简单的查询证明了一点:
SELECT [x], [y]
FROM [dbo].[Example]
ORDER BY FLOOR([x]) --sort performed in execution plan
SELECT [x], [y]
FROM [dbo].[Example]
ORDER BY 2*[x] --NO sort performed in execution plan
SELECT [x], [y]
FROM [dbo].[Example]
ORDER BY 2*[x]+1 --sort performed in execution plan
在任何单一的加法或乘法,查询优化了解到,该数据已经有相同的顺序(这是见过你当组也通过这样的表达)。所以看起来优化器可以理解单调函数的概念,但通常不会被应用。
我现在正在测试计算列/索引解决方案,但似乎这样会大大增加持久数据的大小,因为我需要几个索引来覆盖可能的时间间隔范围。
感谢您的建议亚历克斯。在我实际使用的数据中,域是时间,标准的'datetime'数据类型的分辨率足以满足唯一性(抽样速率比3.33ms更快)。此外,用于对结果进行分组的功能并不总是相同的。在这个例子中,它是“floor”,但是对于实时系列数据,它可以是每30秒,每5分钟,每10天等。我不确定在每个可能的时间间隔内坚持和维护计算列和索引是否切合实际。 – 2011-06-12 00:02:21
@Michael Petito - 重读你的问题,并意识到我没有明确回答你的问题。更新了答案。另外,如果不为您分组的值添加索引,我认为您无法实现良好的性能。 – 2011-06-12 00:08:11
为了回答你的编辑,根据定义,像floor这样的单调(增加)函数满足条件:如果x <= y,那么f(x)<= f(y)'(保存顺序)。所以是的,我的问题的目的是,由于x已经排序,所以f(x)已经排序,因此对于f(x)分组的任何聚合都不需要排序。 – 2011-06-12 00:09:46