1

データがある種のバッチで処理されるデータベースがあり、各バッチには 100 万件のレコードが含まれる場合もあります。コンソール アプリケーションでデータを処理しています。バッチの処理が完了したら、それを完了としてマークし (削除されない場合にもう一度読み取らないようにするため)、削除して次のバッチに進みます。

処理されたデータの「バッチ」を削除する次の単純なストアド プロシージャがあります。

CREATE PROCEDURE [dbo].[DeleteBatch]
(
    @BatchId bigint
)
AS

SET XACT_ABORT ON
BEGIN TRANSACTION
    DELETE FROM table1 WHERE BatchId = @BatchId
    DELETE FROM table2 WHERE BatchId = @BatchId
    DELETE FROM table3 WHERE BatchId = @BatchId
COMMIT
RETURN @@Error

コマンドのタイムアウト値を 10 分に設定して NHibernate を使用していますが、DeleteBatch プロシージャの呼び出しが時折タイムアウトします。

実際には、DeleteBatch が完了するのを待ちたくありません。既にバッチを完了としてマークしているので、保留中のバッチがなくなったら、次のバッチの処理に進むか、コンソール アプリケーションを終了することもできます。

Microsoft SQL Express 2012 を使用しています。

SQL サーバーに伝える簡単な解決策はありますか?

また、DeleteBatch よりも他のクエリの方が重要であるため、DeleteBatch の処理優先度を低く設定できれば素晴らしいと思います。

4

6 に答える 6

3

NHibernateについてはよくわかりません。ただし、このシナリオでADO.NETを使用していた、または使用できる場合は、C#でSqlCommand.BeginExecuteNonQueryメソッドを使用して非同期データベース操作を簡単に実装できます。このメソッドは、Transact-SQLステートメントまたは行を返さないストアドプロシージャを非同期的に実行するプロセスを開始します。これにより、ステートメントの実行中に他のタスクを同時に実行できます。

編集: db操作が終了する前にコンソールアプリを本当に終了したい場合は、コードに手動でスレッドを作成し、それらのスレッドでdb操作を実行する必要があります。System.Thread.Threadを使用して作成されたスレッドはデフォルトでフォアグラウンドスレッドであるため、コンソールアプリを閉じても、これらのスレッドは引き続き有効です。ただし、作成するスレッドの数を検討することも重要です。あなたの場合、バッチごとに1つのスレッドを割り当てる必要があります。バッチの数が非常に多い場合は、多数のスレッドを作成する必要があります。これにより、大量のCPUリソースが消費され、OSが長時間フリーズすることさえあります。

私が提案できるもう1つの簡単な解決策は、BatchIdをデータベーステーブルに挿入することです。そのテーブルにを作成INSERT TRIGGERします。次に、このトリガーは、パラメーターとしてBatchIdを使用してストアドプロシージャを呼び出し、必要なタスクを実行します。
それが役に立てば幸い。

于 2012-09-14T10:13:58.960 に答える
1

コンソール アプリケーションが、バッチを削除しようとする代わりに、バッチ ID を "BatchIdsToDelete" テーブルに書き込むだけだったとしたらどうでしょう。次に、x 分/秒ごとに実行されるエージェント ジョブを使用して、特定のバッチ ID の上位 x パーセントのレコードを削除し、次の x パーセントに取り組む前に少しスリープ状態にすることができます。たぶんそれを見る価値がありますか?

于 2012-09-14T09:40:51.873 に答える
1

パーティーに遅れましたが、他の誰かがこの問題を抱えている場合はSQLCMD. Express を使用すると、ユーザー数が制限されます (2 だと思いますが、前回 Express で多くのことを行ったときから変更されている可能性があります)。sqlcmd、クエリの実行、ストアド プロシージャなどを使用できます。

そしてsqlcmd、Windows スケジューラで開始できます。スクリプト、見通しのルール...

これを使用して、3,000 または 4,000 の SQL Server Express インスタンスを管理し、Windows スケジューラで夜間のメンテナンスをスケジュールしました。

また、PowerShell スクリプトを作成して実行することもできます。これは、より用途が広く、おそらくより広く使用されていsqlcmdます。

于 2018-11-08T22:30:56.133 に答える
0

信頼性の高い非同期プロシージャの実行方法を説明しているこの記事を見てください。コードが含まれています。これはServiceBrokerに基づいています。

.NEt非同期機能(BeginExecute、タスクなど)を使用しようとする場合の問題は、呼び出しの信頼性が低いことです。プロシージャが完了する前にプロセスが終了すると、セッションが切断されるため、サーバーで実行がキャンセルされます。

しかし、タスク自体も確認する必要があります。削除に+10分かかるのはなぜですか。競合によってブロックされていますか?インデックスがありませBatchIdんか?パフォーマンスのトラブルシューティングフローチャートを使用します。

于 2012-09-14T12:56:42.370 に答える
0

私は同じことが必要でした..

長い間検索した後、解決策を見つけましたその最も簡単な方法

        SqlConnection connection = new SqlConnection();
            connection.ConnectionString = "your connection string";

            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString);
            builder.AsynchronousProcessing = true;

            SqlConnection newSqlConn = new SqlConnection(builder.ConnectionString);

            newSqlConn.Open();
    SqlCommand cmd = new SqlCommand(storeProcedureName, newSqlConn);

            cmd.CommandType = CommandType.StoredProcedure;
    cmd.BeginExecuteNonQuery(null, null);
于 2013-02-21T11:07:11.280 に答える