2017-08-30 8 views
0

はクエリです:クエリは1つのデータセットでは遅く実行されますが、別の大きなデータセットではより早く実行されます。 MSSQLサーバー。異なる実行計画。どうして?ここ

以下
select nd1.ansos_id 
from nursdate nd1 
where nd1.division_id = 2 
    and nd1.unit_id = 19 
    and nd1.nursdate_start_date = 
      (select min(nd2.nursdate_start_date) 
      from nursdate nd2 
      where nd2.ansos_id = nd1.ansos_id 
       and nd2.nursdate_start_date >= all 
         (select nd3.nursdate_start_date 
         from nursdate nd3 
         where nd3.ansos_id = nd1.ANSOS_ID 
          and nd3.nursdate_start_date <= '2017-08-13 00:00:00')) 

は最新で

  • 統計の両方のデータセットについても同様です。
  • インデックスの最適化
  • 一般的な両方のデータセットのプロパティは同じです。
  • また、2つのデータセットには、ほぼ同じ量のデータがあります。実際に速く1は、より多くのデータ

を持っている今では1セットで実行するために〜8秒かかりますが、別のデータセットの< 1秒。 ここ遅いデータセット内

  1. 「実行数」&「行の実際の数は」2つのデータセットとの間の実行計画の差であること天文学高い
  2. 速く一つは、追加ノード「インデックススプールを有しています「

スクリーンショット#1:1つのデータセットで同じクエリ、遅い実行計画 enter image description here

スクリーンショット#2:同じクエリ、SPEE別のデータセットで実行計画を実行する enter image description here

この問題を解決する方法は?第1のデータセットで速く動くようにするにはどうすればよいですか? ありがとう!

[EDIT]遅い実行計画(全体「nursdate」テーブルのみ99Kの行を有することに留意されたい) https://www.brentozar.com/pastetheplan/?id=r1ZFFuNt-

高速実行計画(全体「nursdate」表は、333Kの行を有することに留意されたいそれです。何とか速い) https://www.brentozar.com/pastetheplan/?id=rJYMc_EKb

ここで[EDIT]は、データボリューム上のいくつかの情報です。 「mmt」のデータは少ないデータですが、遅く実行されます

--mmt cnt: 99347 
select count(*) 
from mmt_sqa_v60.mmtsqav60.nursdate nd1 

--heo cnt: 333275 
select count(*) 
from heo_sqa_v60_2k12.heosqav602k12.nursdate nd1 

--mmt cnt: 2403 
select count(*) 
from mmt_sqa_v60.mmtsqav60.nursdate nd1 
where nd1.division_id = 2 
and nd1.unit_id = 19 
and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 


--heo cnt: 5537 
select count(*) 
from heo_sqa_v60_2k12.heosqav602k12.nursdate nd1 
where nd1.division_id = 1 
and nd1.unit_id = 20 
and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 
+1

このツールを使用して、両方の実行計画を投稿してください:https://www.brentozar.com/pastetheplan/ – Eli

+1

2つのデータセットは何ですか?彼らは別のテーブルを使用する必要がありますshould notあなたは2つの異なるクエリを持っていますか?クエリで異なるパラメータを使用する場合は、比較できるように2つのクエリも必要です。 –

+1

あなたの質問に対する答えはここにあります。[「実際の行数」と「実行回数」は天文学的に高いです。 410万行9k行データ量の違いの大きさについて話しているため、実行計画は異なる可能性があります。 –

答えて

0

謎解き。それはデータの問題です。 「実行計画」の数が多いから来ているのはここです:

select count(*) 
from mmtsqav60.NURSDATE ndArea 
left outer join mmtsqav60.NURSDATE ndRelated on ndRelated.ANSOS_ID = 
ndArea.ANSOS_ID 
where ndArea.DIVISION_ID=2 and ndArea.UNIT_ID=19; 

結果は、実行計画は、インデックスによって返されるが、ND2とND3に求めていると述べた正確にどのように多くの行である4157613です。上記のロジックは、本質的に、WSMのnursdateクエリーがデータベースサーバーに行うことを要求しているためです。領域のすべてのレコードを検索し、それぞれのレコードについて、そのansos_idのすべてのレコードを検索します。 1つの「ansos_id」には何千ものレコードがあるという点で、データは非現実的なデータです。ここで助けてくれたすべての人に感謝します。

0

問題はありませんが、クエリに問題があります。私はあなたの質問機能がansos_idの前に任意のレコードで見つけると思う@date私が間違っている場合私を修正します。

最も深いレベル

は、前のクエリは、すべてのこれらの日付と比較 @date

select nd3.nursdate_start_date 
from nursdate nd3 
where nd3.ansos_id = nd1.ANSOS_ID 
    and nd3.nursdate_start_date <= '2017-08-13 00:00:00') 

ansos_id前回のためのすべての日付をもたらします。

その後、日付だけが大きくなったり、すべての日付に等しい MAX(date)

あるので、非常に非効率的である

and nd2.nursdate_start_date >= all (...) 

あなたは(select min(nd2.nursdate_start_date)私はすでにだけで1つの日付>= to all

がある説明としてとき、私は言うだろうあなたのクエリはこれで置き換えてください。これは、それぞれの@Dateの前に最後のレコードを返しますansos_id

WITH cte as ( 
    select nd1.ansos_id, nursdate_start_date, 
      RANK() OVER (PARTITION BY ansos_id 
         ORDER BY nursdate_start_date DESC) as rn 
    from nursdate nd1 
    where nd1.division_id = 2 
     and nd1.unit_id = 19 
     and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 
) 
SELECT * 
FROM cte 
WHERE rn = 1 
+0

ここでお手伝いしてくれてありがとう。これは2段階のクエリです。ステップ1:レコード<=対象の日付がある場合は、最新のものを返します。 ステップ2:ステップ1がnullを戻した場合は、最も早いレコード>対象の日付を戻します。 – riceball

+0

私のクエリはステップ1を実行します。しかし、あなたの質問はステップ2もしていないようですね?繰り返すことができますか? –

+0

このクエリはステップ#2を実行します(これは "min"についてです)。いいえ、繰り返される日付ではありません。また、私は別のものを試しました(同じデータベースサーバーの両方のデータセットを持っている)。質問にコメントを追加しました。 – riceball

関連する問題