聚合分组单调函数的冗余排序

Mic*_*ito 8 t-sql sql-server aggregate-functions sql-server-2008

我正在针对包含时间序列中的一堆点的表开发查询.该表可能会变得非常大,因此我希望查询通过在固定时间间隔内平均点来有效地对输出进行下采样.编写查询后,我对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]);
Run Code Online (Sandbox Code Playgroud)

在这里,我有(x,y)对已经按x排序(由于聚集的主键),我对每个整数x平均y(通过截断FLOOR函数).我希望该表已经适合于聚合,因为FLOOR它是单调函数.不幸的是,SQL Server决定需要重新排序这些数据,这是执行计划:

示例执行计划

SQL Server是否能够对已经适当排序的列的单调函数分组的数据执行流聚合?

有没有一种通用的方法来重写这样的查询,以便SQL Server将看到订单被保留?

[更新] 我发现了一篇关于SQL需要的主题的文章:单调函数的sargability,正如标题所暗示的,似乎这是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
Run Code Online (Sandbox Code Playgroud)

在任何单个添加或乘法中,查询优化器都会理解数据已经具有相同的顺序(当您按这样的表达式分组时也会看到这种情况).因此,优化器似乎理解单调函数的概念,但通常不适用.

我现在正在测试计算列/索引解决方案,但看起来这会大大增加持久数据的大小,因为我需要几个索引来覆盖可能的间隔范围.

Ale*_*Aza 3

一些注意事项:

  • 当表为空时您看到的计划和表有 X 行时看到的计划可能是完全不同的计划
  • 我认为在 X 字段上设置主键是不正确的。是否可以有两个点具有相同的 X 值?

我认为如果您执行以下操作,您将获得最佳的查询性能:

create table Point
(
    PointId int identity(1, 1)
        constraint PK_Example_Id primary key,
    X float not null,
    Y float not null,
    FloorX as floor(x) persisted
)

create index IX_Point_FloorX_Y on Point(FloorX, Y)
Run Code Online (Sandbox Code Playgroud)

添加一些行:

declare @RowCount int = 10000
while(@RowCount > 0)
begin
    insert Point
    values (cast(crypt_gen_random(2) as int), cast(crypt_gen_random(2) as int))
    set @RowCount -= 1
end
Run Code Online (Sandbox Code Playgroud)

询问:

select floor(X), avg(Y)
from Point
group by floor(X)
Run Code Online (Sandbox Code Playgroud)

或者

select FloorX, avg(Y)
from Point
group by FloorX
Run Code Online (Sandbox Code Playgroud)

两者都有相同的计划

计划:无排序

在此输入图像描述

另一种选择 - 您可以创建索引视图。在这种情况下,您将必须直接查询视图,除非您有企业版,即使您直接查询表,它也会使用索引视图索引。

[编辑]刚刚意识到我没有明确回答你的问题。X您问如果是聚集主键,为什么 SQL 会执行排序。SQL 不对 执行排序X,而是对 执行排序floor(x)。换句话说,如果x已经排序,那么f(x)顺序不一定相同,对吗?