我有数据样本的表格,有时间戳和一些数据。每个表在时间戳上都有一个聚集索引,然后是一个特定于数据的密钥。数据样本不一定是等距的。避免在SQL Server GROUP BY中进行不必要的排序?
我需要在特定的时间范围内对数据进行缩减采样以绘制图表 - 例如,从100,000行到N,其中N大约是50.虽然我可能不得不妥协于算法的“正确性”从DSP的角度来看,我想保留在SQL中出于性能原因。
我目前的想法是将时间范围内的样本分组到N个框中,然后取每组的平均值。在SQL中实现此目的的一种方法是将分区函数应用于范围从0到N-1(含)的日期,然后是GROUP BY和AVG。
我认为这个GROUP BY可以在没有排序的情况下执行,因为日期来自聚簇索引,分区函数是单调的。但是,SQL Server似乎没有注意到这一点,它发出的代码占执行代价的78%(在下面的例子中)。假设我是对的,这种类型是不必要的,我可以使查询速度提高5倍。
有没有办法强制SQL Server跳过排序?还是有更好的方法来解决这个问题?
干杯。 本
IF EXISTS(SELECT name FROM sysobjects WHERE name = N'test') DROP TABLE test
CREATE TABLE test
(
date DATETIME NOT NULL,
v FLOAT NOT NULL,
CONSTRAINT PK_test PRIMARY KEY CLUSTERED (date ASC, v ASC)
)
INSERT INTO test (date, v) VALUES ('2009-08-22 14:06:00.000', 1)
INSERT INTO test (date, v) VALUES ('2009-08-22 17:09:00.000', 8)
INSERT INTO test (date, v) VALUES ('2009-08-24 00:00:00.000', 2)
INSERT INTO test (date, v) VALUES ('2009-08-24 03:00:00.000', 9)
INSERT INTO test (date, v) VALUES ('2009-08-24 14:06:00.000', 7)
-- the lower bound is set to the table min for demo purposes; in reality
-- it could be any date
declare @min float
set @min = cast((select min(date) from test) as float)
-- similarly for max
declare @max float
set @max = cast((select max(date) from test) as float)
-- the number of results to return (assuming enough data is available)
declare @count int
set @count = 3
-- precompute scale factor
declare @scale float
set @scale = (@count - 1)/(@max - @min)
select @scale
-- this scales the dates from 0 to n-1
select (cast(date as float) - @min) * @scale, v from test
-- this rounds the scaled dates to the nearest partition,
-- groups by the partition, and then averages values in each partition
select round((cast(date as float) - @min) * @scale, 0), avg(v) from test
group by round((cast(date as float) - @min) * @scale, 0)
在这个例子中,应该是很容易分析至少(... - @ min)* @scale部分。不幸的是,将“日期”列存储为浮点数似乎没有什么区别。 但是,最终你说得对:期待SQL Server自动解决这个问题有点乐观。我真正希望的是一种告诉它假设数据已经被排序的方法。 :) 关于FLOAT不精确,我认为DATETIME只是一个FLOAT内部? – 2009-08-22 19:03:25
查看我的日期和浮动'内部'假设的更新。 – 2009-08-22 20:20:08
啊,这很有趣!谢谢。 – 2009-08-22 21:04:38