2

同じ巨大なテーブル (1 億 5000 万を超えるレコード)の 2 つの「インスタンス」間の結合から生成されたレコードを実行するようにカーソルを設定しようとしています。

次の例外メッセージが表示されます。

'PRIMARY' ファイル グループがいっぱいであるため、データベース 'tempdb' のオブジェクト 'dbo.SORT 一時実行ストレージ: 165282123350016' にスペースを割り当てることができませんでした。不要なファイルを削除するか、ファイル グループ内のオブジェクトを削除するか、ファイル グループにファイルを追加するか、ファイル グループ内の既存のファイルに対して自動拡張を設定して、ディスク領域を作成します。

この理由を知っている方はいらっしゃいますか?または、以下のクエリをより効率的にするにはどうすればよいですか?

DECLARE CURSORと最初の の間のどこかで発生することがわかりましたが、それが間にあるFETCH NEXTかどうかはまだわかりません...

  • DECLARE CURSOROPEN

または間

  • OPENそして最初のFETCH NEXT

詳細: SQL ステートメントは次のようになります。

DECLARE cData CURSOR LOCAL FORWARD_ONLY READ_ONLY
為に
  選択する ...
  HugeTable HT1 から HugeTable HT2 に参加 ..
  表 3 を結合 .. 表 4 を結合 .. 表 5 を結合 ..
  どこ ...
  HT1..., HT1... で注文

INSERT INTO SysLog (説明) 値 ('A')

cDataを開く
BEGIN TRANSACTION プロセスデータ
  -- 現在、ここで新しいロギングを試みています:
  -- SysLog に挿入 (説明) 値 ('B')
  cData から NEXT をフェッチ ...
  INSERT INTO SysLog (説明) 値 ('C')
  ...など

最後に取得したログ メッセージは「A」で、1 時間後に上記のメッセージで失敗し、「C」に到達しません。現在、ポイント「B」でログを記録しようとしています。


リクエストに応じて、正確な sql 式を投稿します。

DECLARE cSource CURSOR LOCAL FORWARD_ONLY READ_ONLY
為に
    SELECT MD.sFieldName,
        MD.sFieldValue、
        TR.sTargetDataType、
        MD2.sFieldValue AS sUniqueID、
        TR.sTargetTableName、
        TR.sTargetFieldName、
        I.iRefCustomerID、
        I.iInterfaceID、
        IL.iRefInterfaceSessionID
    マスターデータ MD から
    JOIN マスターデータ MD2
        ON MD.iRowIndex = MD2.iRowIndex
        AND MD.iBatchNumber = MD2.iBatchNumber
        AND MD.sTableName = MD2.sTableName
        AND MD2.sFieldName = 'sUniqueID'
    JOIN SourceTargetRelation TR
        ON MD.sFieldName = TR.sSourceFieldName
        AND MD.sTableName = TR.sSourceTableName
    JOIN インターフェイスログ IL
        ON IL.iInterfaceLogID = MD.iBatchNumber
    JOIN インターフェイス I
        ON I.iInterfaceID = IL.iRefInterfaceID
        AND TR.iRefSystemID = I.iRefSystemID
    どこ
        MD.iBatchNumber = @iBatchNumber
    ORDER BY MD.sTableName、MD.iRowIndex

Quassnoi からの更新された回答の後、元のインデックスもテーブルに投稿します。

このテーブルには、列iBatchNumber、、、、sFieldNameの非クラスター化インデックスがあります。そして、そのインデックスには含まれる列があります。sTableNameiRowIndexsFieldValue


Quassnoi が提案したように (そして、今ではその理由を理解していると思います)、インデックスを変更して、列が 、 、 、 の順序になるようiBatchNumbersTableNameiRowIndexましsFieldNameた。そして、私sFieldValueは含まれている列として使用します。実行計画にはもう何も含まれておらずSORT、実行計画のステップ数は元の半分以下です。これも高速であることを願っています...

4

2 に答える 2

7

この理由を知っている方はいらっしゃいますか?または、以下のクエリをより効率的にするにはどうすればよいですか?

あなたのクエリは を使用していますORDER BY

これにはソートが必要であり、ソートには一時スペースが必要です。あなたはこのスペースの外にいます。

(col_filter_1, col_filter_2, col_order_1, col_order_2)これを回避するには、巨大なテーブルに複合インデックスを作成しcol_filter_nますcol_order_n

このようなインデックスは、フィルタリングと、フィルタリングされた結果の順序付けの両方に使用できます。

実際のクエリ (つまり、フィルター処理して並べ替える式) を投稿すると、そのようなインデックスを作成する方法をより正確に説明できると思います。

アップデート:

(iBatchNumber, sTableName, iRowIndex, sFieldName)あなたのクエリから、 (この順序で)にインデックスが必要であることがわかります。

MD2結合をリードする場合にも役立つ場合があります。

WHERE
    MD2.iBatchNumber = @iBatchNumber
ORDER BY
    MD2.sTableName, MD2.iRowIndex

実行計画を参照し、SORT操作が使用されていないことを確認してください。

于 2009-04-02T11:35:42.087 に答える
0

なぜカーソルを使用しているのですか?特に大きなテーブルでは?セットベースでできないことは何ですか?Cursprs はパフォーマンスが非常に悪いため、別の代替手段が存在する場合は使用しないでください。選択によって見つかったレコードに基づいて別のテーブルに挿入する場合、カーソルがなくてもはるかにうまく実行できます。

于 2009-04-02T14:05:54.973 に答える