問題タブ [sqlbulkcopy]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - WriteToServer:接続プロパティが初期化されていません。sqlbulkcopyエラー
c#でsqlbulkcopyを実行すると、次のエラーが発生します:WriteToServer:接続プロパティが初期化されていません。
WriteToServerコマンドで発生します。接続は開いています。
正しいコード:
sql-server-2005 - SQL Server 2005: 数千または挿入要求のパフォーマンスの向上。ログアウト-ログイン時間 = 120ms
SQL Server 2005 が ADO.NET 2.0 を使用してクライアントによって発行された要求をどのように処理するかについて、誰かが光を当てることができますか? 以下は、SQL トレースの短縮出力です。接続プールが機能していることがわかります (プールされている接続は 1 つだけだと思います)。私には明らかではないのは、以下の for ループの各ループの監査ログイン、SQL:BatchStarting、RPC:Starting、監査ログアウトなど、非常に多くの sp_reset_connection 呼び出しがある理由です。tempdb と master データベースの間で常に切り替えが行われていることがわかります。これにより、次の接続が ConectionString 引数に基づいてプールからフェッチされて作成されたときに、コンテキストが失われたと結論付けることができます。
15 ミリ秒ごとに、1 秒あたり 100 ~ 200 回のログイン/ログアウトを取得できることがわかります (プロファイラーによって同時に報告されています)。15 ミリ秒後、1 秒あたり 100 ~ 200 回のログイン/ログアウトが再び発生します。
これが本番環境での非常に複雑な挿入クエリにどのように影響するかを明確にする必要があります。私は Enterprise Library 2006 を使用しています。コードは VS 2005 でコンパイルされています。これは、親子行をグループ化する 10,000 行のフラット ファイルを解析し、アプリケーション サーバーで実行し、リモート SQL で 2 つのストアド プロシージャを実行するコンソール アプリケーションです。親レコードを挿入する Server 2005 は、Identity 値を取得し、それを使用して 2 番目のストアド プロシージャを 1 回、2 回、または複数回 (場合によっては数千回) 呼び出して、子レコードを挿入します。子テーブルには、5 ~ 10 のインデックスを持つ 1,000 万近くのレコードがあり、その一部は非クラスター化されています。挿入された詳細レコードをアーカイブ テーブルにコピーする非常に複雑な挿入トリガーがあります。全体として、1 秒あたり 7 回の挿入しかありません。つまり、5 万件のレコードに 2 ~ 4 時間かかる可能性があります。
したがって、私の質問は、会社が10万件のレコードをロードし、毎日の計画を立て、フラットファイル注文として来るクライアント要求を満たすためのSLAを持っているため、レコードの挿入を改善する方法があるかどうかです。すぐにインポートされます)。60,000 をインポートするのに 4 時間かかっていたものが、30 分に短縮されます。
DataAdapter の BatchSize を使用して複数のストアド プロシージャ コールを送信したり、SQL Bulk insert を使用して DataReader または DataTable から複数の挿入をバッチ処理したり、SSIS 高速ロードを使用したりしようと考えていました。しかし、インデックスの再作成と統計の人口を適切に分析する方法がわかりません。おそらく、これが完了するまでに時間がかかる可能性があります。さらに悪いことに、会社はレポートに最大のテーブルを使用し、他のオンライン処理とインデックスを削除できません。フィールドに値を設定してトランザクションを手動で管理し、その値を他のアプリケーションがコミットされた行を取得するために使用している新しい値に変更するトランザクション更新を行います。
この問題にアプローチする方法を教えてください。今のところ、別のデータベースに最小限のログを記録し、インデックスを持たないステージング テーブルを作成しようとしています。バッチ処理された (大規模な) 親子挿入を試みます。Production DB には単純な復旧モデルがあると思いますが、完全な復旧になる可能性があります。.NET コンソール アプリケーションで使用されている DB ユーザーが bulkadmin ロールを持っている場合、その一括挿入のログは最小限に抑えられます。テーブルがクラスター化されていて、挿入する多くの非クラスター化インデックスが行ごとにログに記録されることを理解しています。
接続プーリングは機能していますが、多くのログイン/ログアウトがあります。なんで?
for (int i = 1; i <= 10000; i++){ using (SqlConnection conn = new SqlConnection("server=(local);database=master;integrated security=sspi;")) {conn.Open(); using (SqlCommand cmd = conn.CreateCommand()){ cmd.CommandText = "tempdb を使用"; cmd.ExecuteNonQuery();}}}
SQL Server プロファイラー トレース:
監査ログイン マスター 2010-01-13 23:18:45.337 1 - 非プール
SQL:BatchStarting use tempdb master 2010-01-13 23:18:45.337
RPC:Starting exec sp_reset_conn tempdb 2010-01-13 23:18:45.337
監査ログアウトtempdb 2010-01-13 23:18:45.337 2 - プールされた
監査ログイン -- ネットワーク プロトコル マスター 2010-01-13 23:18:45.383 2 - プール
された SQL: BatchStarting は tempdb マスターを使用 2010-01-13 23:18:45.383
RPC: exec sp_reset_conn tempdb 2010-01-13 23:18:45.383 の開始
監査ログアウト tempdb 2010-01-13 23:18:45.383 2 - プール済み
監査ログイン -- ネットワーク プロトコル マスター 2010-01-13 23:18:45.383 2 - プール
された SQL:BatchStarting use tempdb master 2010-01-13 23:18:45.383
RPC:Starting exec sp_reset_conn tempdb 2010-01-13 23:18 :45.383
監査ログアウト tempdb 2010-01-13 23:18:45.383 2 - プール
c# - プロデューサー/コンシューマーパターンとSQLServerDBへのSqlBulkCopyを使用して複数のスレッドを使用してフラットファイルをチャンクで処理する
あなたが私に耐えてくれることを願っています。できるだけ多くの情報を提供したかったのです。主な問題は、値をポップし、それを使用して1つの大きなフラットファイルを処理し、ファイル全体が処理されるまで何度も繰り返し実行する複数のスレッドで使用される構造(スタックなど)を作成する方法です。ファイルに、2.000行のチャンクを使用して5つのスレッドで処理できる100.000のレコードがある場合、各スレッドは10のチャンクを処理します。
私の目標は、フラットファイル内のデータを移動することです(ヘッダー...サブヘッダー...詳細、詳細、詳細、...詳細、サブフッター、サブヘッダー...詳細、詳細、詳細、...詳細、サブフッター、 Subheader ... Detail、Detail、Detail、... Detail、SubFooter、Footer structure)をOLTP DBに入れ、シンプル(フルの可能性あり)から3つのテーブルにリカバリモードを設定します。1つ目はサブヘッダー行に存在するサブヘッダーの一意のキーを表し、2つ目は中間テーブルSubheaderGroupは、2000レコードのチャンクで詳細行のグループ化を表します(FKとしてサブヘッダーのID PKを持ち、3番目はサブヘッダーPKを指すFKを持つ詳細行を表す必要があります。
何万もの詳細行を持つことができ、ロード中に宛先テーブルで0に設定された特別なフィールドを使用し、ファイル処理の最後にこれを変更するトランザクションの更新を行っているため、手動のトランザクション管理を行っています。値を1にすると、ロードが終了したことを他のアプリケーションに通知できます。
このフラットファイルを、複数のスレッドで処理し、宛先テーブルのメタデータから作成されたIDataReaderを使用してSqlBulkCopyを使用してインポートできる、複数の等しい部分(同じ行数)に分割したいと思います。
SqlBulkCopyOptions.TableLockオプションを指定してSqlBulkCopyを使用するには、プロデューサー/コンシューマーパターン(以下のリンクで説明されている-pdf分析とコードサンプル)を使用したいと思います。 http://sqlblog.com/blogs/alberto_ferrari/archive/2009/11/30/sqlbulkcopy-performance-analysis.aspx このパターンにより、複数のプロデューサーを作成でき、同じ数のコンシューマーが行を消費するためにプロデューサーにサブスクライブする必要があります。
TestSqlBulkCopyプロジェクトのDataProducer.csファイルには、数千のレコードの生成をシミュレートするメソッドがあります。
このメソッドは、新しいスレッドのコンテキストで実行されます。この新しいスレッドが元のフラットファイルの一意のチャンクのみを読み取るようにし、別のスレッドが次のチャンクを処理するようにします。次に、コンシューマーは、SqlBulkCopy ADO.NETクラスを使用して、データ(ポンプされたデータ)をSQLServerDBに移動します。
したがって、ここでの質問は、各スレッドでどのlineFromからlineToを処理するかを指示するメインプログラムに関するものであり、これはスレッドの作成中に発生するはずだと思います。2番目の解決策は、おそらくスレッドがいくつかの構造を共有し、それらに固有の何か(スレッド番号やシーケンス番号など)を使用して共有構造を検索し(おそらくスタックと値をポップする(実行中にスタックをロックする)、次のスレッドが次に、次の値を取得します。メインプログラムはフラットファイルを取得し、チャンクのサイズを決定してスタックを作成します。
それで、誰かがいくつかのコードスニペット、複数のスレッドが1つのファイルを処理し、そのファイルの一意の部分のみを取得する方法に関する疑似コードを提供できますか?
ありがとう、ラッド
sql - SQLでデータをコピーしながら列を追加する
SqlBulkCopyを使用して、あるテーブルから別のテーブルにいくつかのレコードを一括挿入しています。クエリはSqlDataReaderを使用してデータを取得しています。テーブル間で重要な(マッピングで処理される列の順序以外の)1つの違いは、宛先テーブルに現在の日付を追加する必要がある日付列があることです。この日付はソーステーブルにありません。これを差し引いて正常に動作している現在のプロセスにこれを追加するにはどうすればよいですか?
現在動作しているコードは次のようになります。
DBはsql2008ENTです。
c# - SqlBulkCopy.WriteToServerがBulkCopyTimeoutに確実に従わない
SqlBulkCopyからのシーケンシャルタイムアウト例外をカウントする必要があります。これをテストするために、外部アプリを使用してトランザクションを開始し、ターゲットテーブルをロックします。
SqlBulkCopyは、最初の呼び出しでのみ、予期したときにタイムアウト例外をスローします。外部接続とトランザクション、および接続文字列と内部トランザクションを使用してみました。外部接続とトランザクションでは、接続を開いたり、トランザクションを開始またはコミットしたりするのに無限の待機が発生することはありませんでしたが、常にで待機していました.WriteToServer()
。
制限SqlBulkCopy.WriteToServer()
に達したときにタイムアウト例外を確実にスローする、これに対するいくつかのアプローチはありますか?.BulkCopyTimeout
ブロックのスコープ内で例外を処理するのではなく、例外をバブルアップさせる方using
が好きですが、いつでも再スローできます。洞察に感謝します。
アップデート1:
まだ解決策はありません。ただし、興味深い動作が発見されました。通常のSqlCommandは、SqlBulkCopy.WriteToServerメソッドが無期限にハングするのと同じロック中に、期待どおりにTimeoutExceptionをスローします。
SqlBulkCopy.WriteToServerが予期したときに一貫してタイムアウトをスローするようにするために、私たちが試した(そして失敗した)アプローチは次のとおりです。
- MARS(複数のアクティブな結果セット)のオン/オフ
- TableLockのオンとオフ
- ヒープテーブルとインデックステーブルとしての宛先
- より長い/より短いBulkTimeout値(10秒から5分)
- 内部トランザクションと外部トランザクション
今のところ、回避策として、a)WriteToServer呼び出しを非同期ラッパーに入れて、自分で時間を計ることができるようにすることと、b)WriteToServerを1回だけ呼び出すことを交互に行っています。タイムアウト後、通常のSqlCommandが成功するまで待ってから、 WriteToServerを再試行してください。これらのアプローチを使用することで、少なくとも実行フローの制御を維持することができます。
c# - バルクコピーのロールバック
c#の一括コピークラスでデータベースからコピーを作成するアプリケーションがあります。
例外が発生したときにSQLサーバーで一括コピーアクションをロールバックできますか?
c# - SqlBulkCopy WriteToServer の例。私は何を間違っていますか?
これは長いかもしれませんが、私の例を説明したいと思います
私はこのコードを手に入れました:
実行すると、子テーブルの FK 列に「見える」データが正しく表示されました。(0 と 1) 問題は、保存後にデータがデータベースに取得されることですが、それで問題ありません。親テーブルから FK ID を取得する代わりに、C# コードから 0 と 1 を取得しました。注: DB 内のテーブルには FK 制約があります。そのようなものを手動で追加することはできませんが、 SqlBulkCopy WriteToServer には問題がなく、とにかく間違ったデータを書き込みます(制約がチェックされていないようです)
テーブルを見てください:
結果は次のようになります。
私は何を間違っていますか?おそらく、C# でこのような ID を取得することは想定されていません。しかし、どのように?それとも可能ですか?つまり、私の 2 番目のバルク挿入がどのようにして SQL を知ることになるのかということです!!!! 挿入時のID?
c# - 型指定された List から IDataReader を取得する
私はList<MyObject>
百万の要素を持つ を持っています。(実際には SubSonic コレクションですが、データベースからロードされません)。
現在、次のようにSqlBulkCopyを使用しています。
SubSonic の MyObjectCollection.ToDataTable() を使用して、コレクションから DataTable を構築します。ただし、これはメモリ内でオブジェクトを複製し、非効率的です。コレクションをメモリ内で複製しないように、DataTable の代わりに IDataReader を使用する SqlBulkCopy.WriteToServer メソッドを使用したいと考えています。
リストから IDataReader を取得する最も簡単な方法は何ですか? カスタムデータリーダーを実装できると思います(ここのようにhttp://blogs.microsoft.co.il/blogs/aviwortzel/archive/2008/05/06/implementing-sqlbulkcopy-in-linq-to-sql.aspx)ですが、一般的なコードを書かなくても、もっと簡単にできることがあるはずです。
編集: オブジェクトのコレクションから IDataReader を簡単に生成できるようには見えません。フレームワークに組み込まれたものを望んでいましたが、現在の回答を受け入れています。
sql - データベース エンジンに依存しない SqlBulkCopy の類似物
膨大な量のデータをロードするための、データベース エンジンに依存しない最適な方法は何ですか。
SQL Server を使用しているときに SqlBulkCopy を使用しているが、SQL Server から切り離したい
sql-server - bcp コマンドの実行で一貫性がない
2 台のコンピューターで bcp コマンドを実行します。最初のコンピューターには Windows XP があり、2 番目のコンピューターには Windows Server 2003 があります。最初にコマンドを実行すると、bcp は正常に実行されますが、2 番目のコンピューターでこれを実行すると、次のエラーが発生します。
何が問題ですか?