3

mssql サーバー 2008r2 を使用しています。私は、19 店舗の売上高データを日ごとにアイテムごとに含む巨大なテーブルを持っています。約1億行あります。しかし、分割ビューを使用すると、クエリを簡単に実行できます。

テーブルの構造は次のようになります。

  1. 店舗名
  2. アイテムID
  3. 日にち
  4. ひっくり返す
  5. 販売数量

出力レポートは次のようになります: アイテム ID、日付、store_1.turnover、store_1.quantity、store_2.turnover、store_2.quantity....

この種のレポートを作成するには、次のクエリを使用します。

WITH cte_sell AS(
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418' )

SELECT a.item_id,a.date,
    store_1.turnover,store_1.quantity,
    store_2.turnover,store_2.quantity,
    store_3.turnover,store_3.quantity

FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 1') as Store_1 ON a.item_id=store_1.item_id and a.date=store_1.date    
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 2') as Store_2 ON a.item_id=store_2.item_id and a.date=store_2.date    
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 3') as Store_3 ON a.item_id=store_3.item_id and a.date=store_3.date

クエリを理解していただければ幸いです。

クエリは、14 ~ 15 のストア (14 15 LEFT JOIN) に対して 10 秒未満で実行されます。これは適切です。しかし、問題は、19 のストア (19 の LEFT JOIN) をすべて選択すると、クエリが劇的に遅くなることです。完了するまでに 2 ~ 3 分かかる場合があります。

実行計画の作成も非常に長くなります。

  • 12店舗限定2秒
  • 19店舗22秒

テーブルの結合に制限はありますか? 巨大なクエリを制御するサーバーパラメーターがいくつかあると思います。クエリまたはサーバーを最適化する方法を知っている人はいますか?

最悪の場合、サーバーがフリーズすることがあります。クエリが 9 時と 12 時に実行されている間に、トレース ファイルを作成しました。9 時に、クエリの実行に 2 分かかりました。12 時に、構成マネージャーから SQL サービスを再起動できないため、10 分後にコンピューターを再起動する必要がありました。

スクリーンショットを添付できません。

アクティビティ モニターでは、プロセスは一時停止状態にあります。待機タイプ: CXPACKET 待機リソース: exchange.... 申し訳ありませんが、ロックについてはよくわかりません。

管理スタジオから接続しようとしたところ、次のメッセージが表示されました。サーバーとの接続は正常に確立されましたが、ログイン プロセス中にエラーが発生しました。(プロバイダー: TCP プロバイダー、エラー:0 (ハンガリー語からの翻訳): 既存の接続がリモート マシンによって強制的に閉じられました。

4

2 に答える 2

1

サブクエリを削除して、結合条件のみを使用することを検討しましたか?

WITH cte_sell AS(
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418' )

SELECT a.item_id,a.date,
    store_1.turnover,store_1.quantity,
    store_2.turnover,store_2.quantity,
    store_3.turnover,store_3.quantity

FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a
LEFT JOIN cte_sell as Store_1 ON a.item_id=store_1.item_id and a.date=store_1.date and Store='Store 1'
LEFT JOIN cte_sell as Store_2 ON a.item_id=store_2.item_id and a.date=store_2.date and store='Store 2'
LEFT JOIN cte_sell as Store_3 ON a.item_id=store_3.item_id and a.date=store_3.date and store='Store 3'
于 2013-05-01T16:36:43.760 に答える
0

問題は、SQL Server が CTE 式をクエリに複数回表示されたときに最適化していないように見えることだと思います。つまり、実行計画を見ると、メンション ストアごとにビューが 3 回実行されています。

各店舗を別の列に並べることはできますか? もしそうなら、これを試してください:

WITH cte_sell AS (
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418'
   )
SELECT a.item_id, a.date, store, turnover, quantity
FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a left join
     cte_sell cs
     on a.item_id=cs.item_id and a.date=cs.date and cs.store in ('Store 1', 'Store 2', 'Store 3')

複数のストアを含む 1 行が必要な場合は、条件付き集計 orpivotが問題を解決します。

すべての値を 1 行で表示する場合は、上記のクエリで条件付き集計を使用します。

WITH cte_sell AS (
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418'
   )
SELECT a.item_id, a.date,
       max(case when store = 'Store 1' then turnover end),
       max(case when store = 'Store 1' then quantity end),
       max(case when store = 'Store 2' then turnover end),
       max(case when store = 'Store 2' then quantity end),
       max(case when store = 'Store 3' then turnover end),
       max(case when store = 'Store 3' then quantity end)
FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a left join
     cte_sell cs
     on a.item_id=cs.item_id and a.date=cs.date and cs.store in ('Store 1', 'Store 2', 'Store 3')
group by a.item_id, a.date
于 2013-05-01T15:38:39.237 に答える