私はタイムスタンプといくつかのデータを持つデータサンプルのテーブルを持っています。各テーブルには、タイムスタンプ上にクラスタ化されたインデックスがあり、次にデータ固有のキーがあります。データサンプルは必ずしも等距離にあるとは限りません。SQL ServerのGROUP BYで不必要な並べ替えを避ける?
グラフを描画するために、特定の時間範囲のデータをダウンサンプリングする必要があります。たとえば、100,000行からN(Nは約50)です。アルゴリズムの「正確さ」を妥協する必要がありますDSPの観点からは、パフォーマンス上の理由からSQLでこれを保持したいと思います。
私の現在のアイデアは、時間範囲のサンプルをN個のボックスにグループ化し、各グループの平均を取ることです。 SQLでこれを達成する1つの方法は、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)
この例では、少なくとも分析するのは非常に簡単にする必要があります(... - 分)* @スケール部分。残念ながら、 "日付"の列を浮動小数点として格納しても差はありません。 最終的には正しいですが、SQL Serverがこれを自動的に解決することを期待するのはちょっと楽観的です。私が本当に望んでいるのは、データがすでにソートされていると仮定するように指示する方法です。 :) FLOATは不正確ですが、DATETIMEは内部的に単なるFLOATだと思いましたか? –
日付と浮動小数点の「内部」仮定に関する私の更新を見てください。 –
ああ、それはとても面白い!ありがとう。 –