SQL2008を使用して、日付が特定のターゲット日付に最も近い行を見つける効率的なクエリを見つけようとしています。効率的な「最も近い数値または日付を見つける」日付/数値の列がインデックスでカバーされている
私のテーブルにはすでに日付が最初の列であるカバリングインデックスがあるため、明らかに非効率的な解決策があります(たとえば、ABS and DATEDIFFを使用したテーブルスキャン)。正確にどの行が最も近いかを調べる前に、その索引を使用して結果を絞り込むことができます。
理論的には、単一のインデックスルックアップを使用してクエリを満たし、そのインデックスから2行のデータを順次取得する必要があります。
しかし、これまでのところ、私はこの1つ以上の最適解を見つけることができませんしてきた:
DECLARE @target DATETIME = '01/02/2011'
SELECT TOP 1 Val, Measured
FROM (
SELECT TOP 1 Val, Measured
FROM tbl
WHERE Measured <= @Target
ORDER BY Measured desc
UNION ALL
SELECT TOP 1 Val, Measured
FROM tbl
WHERE Measured >= @Target
ORDER BY Measured asc
) x
ORDER BY ABS (DATEDIFF (second, Measured, @Target))
これは(4論理は、以下の試験スキーマに高速に読み込みされ、9論理は私の現実世界に読み込みますテーブル)が、まだ2スキャンカウントのソリューションです。このインデックスに一度しかヒットしないより効率的なソリューションはありますか?
2番目のインデックスシークは最初のシークによってアクセスされたキャッシュされたページを引き出すので、既存のソリューションで十分です(可能な場合でも)
ここにスキーマとサンプルデータがあります。結果のクエリプランは、私のより複雑なテーブルと同じであるが、両方は、私の実際のスキーマから単純化されています
CREATE TABLE tbl
(
ID int IDENTITY(1,1) PRIMARY KEY CLUSTERED NOT NULL,
Measured DATETIME NOT NULL,
Val int NOT NULL
);
CREATE NONCLUSTERED INDEX IX_tbl ON tbl (Measured) INCLUDE (Val)
INSERT tbl VALUES ('2011-01-01 12:34',6);
INSERT tbl VALUES ('2011-01-01 23:34',6);
INSERT tbl VALUES ('2011-01-03 09:03',12);
INSERT tbl VALUES ('2011-02-01 09:24',18);
INSERT tbl VALUES ('2011-02-08 07:12',7);
INSERT tbl VALUES ('2011-03-01 12:34',6);
INSERT tbl VALUES ('2011-04-03 09:03',12);
INSERT tbl VALUES ('2011-05-01 09:24',18);
INSERT tbl VALUES ('2011-06-08 07:12',7);
-- insert another few million rows here to compare to my real-world table
''01/02/2011 'を測定したtblからの最小値('01/02/2011'を測定したもの)それとも効率が悪いですか? –
あなたは9つの論理読み取りについて苦情を申し立てていますか?これがあなたが持っている最大のパフォーマンス上の問題であれば、多分余裕があります。 :-)しかし、他にもいくつかの考えがありますが、より多くのメタが必要です。たとえば、毎日少なくとも1つの行が確実に存在するように、この表に十分なエントリーを持っていますか? @targetは常に日付全体になりますか? –
@userが不明な場合、MAX/MINはTOPとほぼ同じ性能を発揮しますが、MAXの場合はValを簡単に取得できません。 –