7

私はこれを試したことがないので、メモリの問題が発生したかどうかはわかりません。

しかし、SqlDataReaderは1兆レコードを読み取ることができますか?それはすべて正しくストリーミングされていますか?私は、SQL/TDSプロトコルが内部で何をしているのかについて少し理解しています。

更新 トリリオンを非常に大きな数を意味するように翻訳します。たぶん10億か1億のようなことを言うべきだったでしょう。

4

3 に答える 3

14

詳細がいくつかあります。

  • SqlDataReaderは通常、メモリ内の行全体を読み取り、それをキャッシュします。これには任意のBLOBフィールドが含まれるため、最終的に複数の2GBフィールドをメモリ(XML、VARBINARY(MAX)、VARCHAR(MAX)、NVARCHAR(MAX))にキャッシュすることになります。このようなフィールドが問題になる場合は、CommandBehavior.SequentialAccessExecuteReaderに渡し、 SqlBytes.StreamなどのSqlClient固有のタイプのストリーミング機能を使用する必要があります。

  • SqlDataReaderが完了するまで、接続はビジーです。これにより、接続がビジーであるために同じトランザクションでデータベース内の処理を実行できなくなるため、トランザクションの問題が発生します。ループバック分散トランザクションが禁止されているため、別の接続を開いて同じトランザクションに登録しようとすると失敗します。解決策はMARSを使用することです。これを行うには、接続を設定MultipleActiveResultSets=Trueします。これにより、データリーダーがアクティブなときに同じ接続でコマンドを発行できます(通常はfetch-process-fetchループ)。Christian Kleinermanのリンクを注意深く読み、MARSとトランザクションに関する問題と制限を理解していることを確認してください。これらは非常に微妙で、直感に反しています。

  • クライアントでの処理に時間がかかると、サーバーがブロックされます。クエリは引き続き実行され、通信パイプがいっぱいになったときにサーバーはクエリを一時停止する必要があります。クエリはワーカー(並列プランの場合はそれ以上)を消費し、サーバーでは作業は非常に希少な商品です(おおよそスレッドに相当します)。多くのクライアントが自分の余暇で膨大な結果セットを処理する余裕はありません。

  • トランザクションサイズ。1つのトランザクションで1兆件のレコードを処理することは、決してうまくいきません。ログはトランザクション全体に対応するために拡張する必要があり、VLFを切り捨てて再利用しないため、ログが大幅に増加します。

  • 回復時間。999億番目のレコードで処理が失敗した場合、実行されたすべての作業をロールバックする必要があるため、ロールバックするだけでさらに「12」日かかります。

于 2009-12-04T20:17:47.843 に答える
11

はい、それはストリーミングされます...しかし、私はあなたが実際にそれをやろうとすべきではないと思います。

1秒あたり100万レコードを読み取ることができたとしても(私にはそうは思えませんが)、1兆レコードを読み取るにはまだ12日必要です...途中で失うリスクを冒すには多くの作業が必要です。

文字通り、1兆レコードを読みたくないと思うかもしれませんが、とにかく「大量の」作業を論理バッチに分割できるのであれば、それはおそらく良い考えです。

于 2009-12-04T19:35:44.333 に答える
1

はい-しばらく時間がかかる場合がありますが(SQLがスナップショットなどを取得しようとして愚かなことをしていない限り)、サーバーがそれをストリーミングできる場合は、SqlDataReaderにメモリ使用量の問題はありません。

于 2009-12-04T19:37:06.087 に答える