0

テーブル

  • TEST_RUNS (ID int、Date_Time datetime、Row1 int、Row2 int、Row3 int、Row4 int)
  • ADMIN_TIME_FILTER (ID int、名前 varchar(20)、Start_Date 日時、End_Date 日時)

ADMIN_TIME_FILTERは、自動化によって頻繁に更新されるシフトする日付範囲の小さなリストを保持します。一般的な日付範囲 (ThisYear、ThisDay など) と、いくつかの難解な範囲があります。このテーブルは、結合で TEST_RUNS からデータを除外する方法として厳密に存在します。

TEST_RUNSには、関心のある実際のデータが保持され、何百万もの行があります。これら 2 つのテーブルを結合する一連の定義済みビューがあるため、ADMIN_TIME_FILTER テーブルを更新するだけで、変更をビューに反映させることができます。日付以外に、これら 2 つのテーブルをリンクする行はありません。

クエリ

問題は、推定された行数が大幅にずれているため、クエリのパフォーマンスが低下することです。これは、悪い見積もりを示す単純なクエリです。

with test as (
    SELECT a.* FROM TEST_RUNS a
    INNER JOIN ADMIN_TIME_FILTER b ON b.ID = 5 -- ID for ThisYear range
       AND a.date_time BETWEEN b.start_date AND b.end_date
)
select count(*) from test 

クエリプランは次のとおりです。

クエリプラン

統計は問題ではありません。次のクエリを実行して、正確な行の見積もりを取得できます

with test as (
    select tr.* from test_runs tr
    where tr.date_time between '2012-01-01 00:00:00' and '2012-12-31 00:00:00'
)
select count(*) from test

ヘルプ

結合方法から切り替えるのは簡単な作業ではないため、行の見積もりを改善するための代替手段を探しています。

インデックス付きビューは、パフォーマンスへの影響により、実行可能なオプションではないようです。

4

1 に答える 1

2

問題は行数ではありません。クエリが非等結合として設定されています。入れ子になったループを使用する以外に、SQL Server が結合を処理する方法は他にありません。

「a」テーブルに ID がある場合は、次の方法が役立つ場合があります。

with test as (
    SELECT a.*
    FROM TEST_RUNS a INNER JOIN
         ADMIN_TIME_FILTER b
         ON a.id = b.id and b.ID = 5 and -- ID for ThisYear range
            a.date_time BETWEEN b.start_date AND b.end_date
)
select count(*) from test 

テーブル間の「id」を照合することで、SQL Server はマージ結合やハッシュ結合などの他の結合アルゴリズムを考慮することができます。

これを修正する別の方法があるのではないかと思います。B のインデックスは何を使用していますか? (id, start_date, end_date) をお勧めします。エンジンは、クエリを満たすために日付にインデックスを使用することを決定している可能性があります。

于 2012-10-05T20:46:53.170 に答える