.Net 4.0 と SQL サーバー 2008 R2 を使用しています。
何百万もの結果を返し、完全に実行するのに長い時間がかかる大きな SQL 選択クエリを実行しています。
クエリ全体が完了するのを待たずに、クエリによって返された結果の一部のみを読み取る方法を知っている人はいますか?
つまり、クエリがまだ実行されていて、次の結果を取得している間に、最初の 10,000 レコード チャンクを読み取りたいと考えています。
.Net 4.0 と SQL サーバー 2008 R2 を使用しています。
何百万もの結果を返し、完全に実行するのに長い時間がかかる大きな SQL 選択クエリを実行しています。
クエリ全体が完了するのを待たずに、クエリによって返された結果の一部のみを読み取る方法を知っている人はいますか?
つまり、クエリがまだ実行されていて、次の結果を取得している間に、最初の 10,000 レコード チャンクを読み取りたいと考えています。
クエリ自体がストリーミングされているかどうか、または一時テーブルで多くの作業を行ってから(最終的に)データを返し始めるかどうかに一部依存します。2番目のシナリオでは、クエリを書き直す以外に多くのことを行うことはできません。ただし、最初のケースでは、通常、イテレータブロックが役立ちます。
public IEnumerable<Foo> GetData() {
// not shown; building command etc
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {
Foo foo = // not shown; materialize Foo from reader
yield return foo;
}
}
}
これはストリーミングイテレータになりました。これをforeach
超えると、最初にすべてのデータをバッファリングすることなく、着信TDSデータからライブでレコードを取得できます。
(おそらく賢明に)独自のマテリアライゼーションコードを記述したくない場合は、これを実行するツールがあります。たとえば、LINQ-to-SQLExecuteQuery<T>(tsql, args)
は上記を簡単に実行できます。
データページングを使用する必要があります。
SQL Server には TOP 句 ( SQL TOP 10 a,b,c from d ) とBETWEENがあります。
SELECT TOP 10000 a,b,c from d BETWEEN X and Y
これがあれば、N 個の行を取得し、部分的な処理を行ってから、次の N 個の行をロードすることができると思います。
これは、マルチスレッド ソリューションを実装することで実現できます。1 つは結果を取得し、もう 1 つはデータを非同期に待機し、何らかの処理を行います。
本当に何百万ものレコードを処理する必要がある場合は、ラウンドごとに10,000をロードして処理してから、次の10,000をロードしないのはなぜですか。データベースのパフォーマンスはロジックレイヤーよりもはるかに優れているため、データをロードする前にDBMSを使用してデータをフィルタリングすることを検討しないでください。
または、遅延読み込みの概念に従い、必要な場合にのみ実際のデータを読み込むIDのみを読み込みます。