7

レコードTable Valued Constructorを選択しています。別のテーブル1 millionに使用されます。update

SELECT *
FROM   (VALUES (100,200,300),
               (100,200,300),
               (100,200,300),
               (100,200,300),
               .....
               ..... --1 million records
               (100,200,300)) tc (proj_d, period_sid, val) 

ここに私の元のクエリがあります: https://www.dropbox.com/s/ezomt80hsh36gws/TVC.txt?dl=0#

上記を実行すると、クエリがエラーで完了し、エラーメッセージが表示さselectれるだけです。

ここに画像の説明を入力

更新:ブロックを使用してエラーメッセージまたはエラー番号をキャッチしようとしましたTRY/CATCHが、前の画像と同じエラーはまだ使用されていません

BEGIN try
    SELECT *
    FROM   (VALUES (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    .....
                    ..... --1 million records
                    (100,200,300)) tc (proj_d, period_sid, val) 
END try

BEGIN catch
    SELECT Error_number(),
           Error_message()
END catch 

実行されていないのは、の Table Valed コンストラクターに制限があるためですSelect。私はInsertそれを知っていますが1000、ここで選択しています。

4

2 に答える 2

3

関連するハード コードされた制限はありません (65,536 * 4 KB のネットワーク パケット サイズは 268 MB であり、スクリプトの長さはそれに近いものではありません) が、大量の行に対してこの方法を使用することはお勧めできません。

表示されているエラーは、SQL Server ではなくクライアント ツールによってスローされます。動的SQLコンパイルでSQL文字列を構築すると、少なくとも正常に開始できます

DECLARE @SQL NVARCHAR(MAX) = '(100,200,300),
';

SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL, 1000000) + '
(100,200,300)) tc (proj_d, period_sid, val)';

SELECT @SQL AS [processing-instruction(x)]
FOR XML PATH('')

SELECT DATALENGTH(@SQL) / 1048576.0 AS [Length in MB] --30.517705917

EXEC(@SQL);

〜30分のコンパイル時間後に上記を殺しましたが、それでも行は生成されませんでした。リテラル値は、定数のテーブルとしてプラン自体の内部に格納する必要があり、SQL Server はそれらのプロパティを導出するために多くの時間を費やします。

SSMS は 32 ビット アプリケーションでありstd::bad_alloc、バッチの解析中に例外をスローします。

ここに画像の説明を入力

容量に達した Token のベクトルに要素をプッシュしようとしましたが、十分な大きさの連続したメモリ領域が利用できないため、サイズ変更の試みは失敗しました。したがって、ステートメントはサーバーに到達することさえありません。

ベクトルの容量は毎回 50% 増加します (つまり、ここのシーケンスに従います)。ベクトルを拡張する必要がある容量は、コードのレイアウト方法によって異なります。

以下は、容量を 19 から 28 に増やす必要があります。

SELECT * FROM 
(VALUES 
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300)) tc (proj_d, period_sid, val)

以下はサイズ2のみを必要とします

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val)

以下では、63 以上、94 以下の容量が必要です。

SELECT *
FROM   (VALUES 
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300)
       ) tc (proj_d, period_sid, val) 

ケース 1 のようにレイアウトされた 100 万行の場合、ベクトル容量は 3,543,306 に増加する必要があります。

次のいずれかにより、クライアント側の解析が成功することがわかる場合があります。

  1. 改行の数を減らします。
  2. アドレス空間の断片化が少ないときに、大きな連続メモリの要求が成功することを期待して、SSMS を再起動します。

ただし、サーバーに正常に送信したとしても、上記で説明したように、実行計画の生成中にサーバーを強制終了するだけです。

インポート エクスポート ウィザードを使用してテーブルをロードする方がはるかに優れています。TSQL で実行する必要がある場合は、小さなバッチに分割したり、XML の細断処理などの別の方法を使用したりすると、テーブル値コンストラクターよりもパフォーマンスが向上します。たとえば、次のコードは私のマシンでは 13 秒で実行されます (ただし、SSMS を使用している場合は、大規模な XML 文字列リテラルを貼り付けるのではなく、複数のバッチに分割する必要があります)。

DECLARE @S NVARCHAR(MAX) = '<x proj_d="100" period_sid="200" val="300" />
' ; 

DECLARE @Xml XML = REPLICATE(@S,1000000);

SELECT 
    x.value('@proj_d','int'),
    x.value('@period_sid','int'),
    x.value('@val','int')
FROM @Xml.nodes('/x') c(x)
于 2016-11-07T21:44:48.330 に答える
0

クエリの制限については、こちらを確認してください: https://msdn.microsoft.com/en-us/library/ms143432.aspx

于 2016-11-07T08:26:26.083 に答える