インデックスのないSQLServerテーブルがあり、追加できません。そのテーブルには何百万ものレコードがあり、メモリが不足しているため、1回のクエリですべてのレコードを取得することはできません。
すべてのレコードを小さな部分で取得するにはどうすればよいですか(たとえば、部分ごとに100レコード)。
インデックスのないSQLServerテーブルがあり、追加できません。そのテーブルには何百万ものレコードがあり、メモリが不足しているため、1回のクエリですべてのレコードを取得することはできません。
すべてのレコードを小さな部分で取得するにはどうすればよいですか(たとえば、部分ごとに100レコード)。
どのように記録を読み取ろうとしていますか? を使用する場合SqlDataReader、メモリ不足の問題は発生しません。
const string QUERY = "SELECT * FROM MyTable";
using (var conn = new SqlConnection(CONNECTION_STRING))
{
using (var cmd = new SqlCommand(QUERY, conn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Use properties and methods of the reader to access the current row
}
}
}
}
これにより、データベース接続全体で一度に 1 行が渡されます。接続はバッファリングを行い、データベースから複数の行を取得して、一度に 1 つずつ渡します。
これは、カーソルを実際の目的で使用できるまれなケースの 1 つです。
静的カーソルを作成し (これにより、テーブル データのコピーが作成されますが、クライアント側ではなくサーバーの一時データベースに作成され、並べ替えられます)、このカーソルを参照できます。
解決策の 1 つは、Quassnoi が既に提案したように、サーバー側のカーソルを使用することです。その欠点は、テーブル全体のコピーが tempdb に作成されることを意味する静的カーソルでなければならないことです。
別の解決策は、クライアント側をストリーム指向の方法で行ごとに処理することです (つまり、クライアント側のカーソル)。
using(SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (rdr.Read())
{
-- process one row here
}
}
このようにして、クライアント側のメモリをすべて使い果たすことなく、大きな行セットを処理できます。
1 つの解決策は、ダンプする必要があるすべてのテーブルを ID 列のある一時テーブルに選択することです。私は別々のアプリケーションサーバーとデータベースサーバーを持っており、DBサーバーにはこれに十分なメモリがあるため、これは...許容できるソリューションです。しかし、おそらくもっと効果的な解決策がありますか?