1

AWS SES を使用して大量のメールを送信する必要があります (ジョブごとに 10,000 など)。並行して行う方法についてのすばらしいブログを見つけたので、送信トランザクション データを DB に書き込む方法について質問があります。私は npoco ORM と InsertBulk を使用しています。これは、ざっと見てから、接続を開き、各 poco を反復して挿入し、接続を閉じます。送信ごとの開始、書き込み、および終了を除いて、これはステップアップです。ここでの私の考えは、DB操作を最小限に抑えることですが、サーバーまたはジョブの中断が発生した場合に備えて、50回程度の電子メール送信ごとにDBに書き込む必要があります。ジョブは、重複を送信せずに中断したところから再開できます。 .

そのため、ConcurrentBag、スレッドロック、リストへの変換、そのリストを npoco に送信して挿入するなどの使用を開始しました。非常に限定的にテストされ、動作します。しかし、それは適切な方法ではないと確信しており、ここで適切にスレッド化を使用している自信がありません。このシナリオでの提案は何ですか? 挿入のために、concurrentbag を npoco に渡す方がよいか、実行可能でしょうか。他の挿入方法はありますか?

 var bag = new ConcurrentBag<EmailSent>();
    Parallel.ForEach(recipients.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = maxParallelEmails },
          recipient =>
           {
         var response = client.SendEmail(request);
          bag.Add(new EmailSent() { JobId = jobId, MessageId = response.MessageId});
       }
    lock (syncRoot) 
        {
             count++;
             if (count % 50 == 0 || count == recipients.Count) 
              {
               var list = new List<EmailSent>();
                 while (!bag.IsEmpty)
                  {
                   EmailSent email;
                     if (bag.TryTake(out email))
                      {
                        list.Add(email);

                      }

               }
            repo.InsertBulk<EmailSent>(list);
       }
});
4

2 に答える 2

1

最適化だけを探している場合は、挿入にテーブル値パラメーターを使用して、挿入ごとに 1 回呼び出すのではなく、複数のレコードをストアド プロシージャに送信します。

SQL サーバーでは、パラメーターの型を定義します。これは、テーブルを定義するのとよく似ています。(ほとんどのサンプルは上記のリンクからのものです。)

CREATE TYPE dbo.CategoryTableType AS TABLE
( CategoryID int, CategoryName nvarchar(50) )

次に、そのタイプのパラメーターを挿入プロシージャーに追加します。

CREATE PROCEDURE usp_UpdateCategories 
(@tvpNewCategories dbo.CategoryTableType READONLY)

ストアド プロシージャ内では、テーブル変数であるかのように、そのパラメーターから選択できます。

INSERT INTO dbo.Categories (CategoryID, CategoryName)
SELECT nc.CategoryID, nc.CategoryName FROM @tvpNewCategories AS nc;

これの良いところは、すべての挿入を 1 回の操作で実行できることです。

アプリケーション側では、定義したテーブル タイプに対応する DataTable を作成します。次に、挿入するレコードをテーブルに入力します。

最後に、プロシージャを呼び出すときに、DataTable を値としてパラメータを追加し、SqlDbType = SqlDbType.Structured'TypeName' がテーブル タイプの名前であることを指定します。

SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
"@tvpNewCategories", yourDataTable);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.CategoryTableType";

2008 年以前に SQL サーバーを使用していた場合は、文字列の連結や XML の送信と解析など、複数のレコードをプロシージャに渡すためにいくつかの奇妙なことを行ったことをご存知でしょう。これははるかに簡単で、個々のストアド プロシージャ呼び出しの数を大幅に削減できます。

于 2016-03-13T19:22:31.937 に答える