2

SQL2008 を使用して、日付が特定のターゲット日付に最も近い行を見つけるための効率的なクエリを見つけようとしています。

私のテーブルには日付が最初の列であるカバリング インデックスが既にあるため、私が気にしなかった明らかな非効率的な解決策 (たとえば、ABS および DATEDIFFを使用したテーブル スキャン) があります。どの行が最も近いかを正確に把握する前に、そのインデックスを使用して結果を絞り込むことができます。

理論的には、1 回のインデックス ルックアップと、そのインデックスからの 2 行のデータの連続プルを使用して、クエリを満たすことができるはずです。

しかし、これまでのところ、これよりも最適なソリューションを見つけることができませんでした:

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
4

1 に答える 1

1

最初に @target がテーブル内のどこにあるかを判断し、次に +1 / -1 の検索範囲を 1 日または 1 週間以内に限定することを検討してください。次に、そのセット内で日付で並べ替えて最も近いものを見つけると、両側のセット全体に TOP 1/ORDER BY を適用するよりもコストがかかりません。

于 2011-07-19T16:38:11.310 に答える