2

メールの送信とメールのバウンスを照合して、配信されたかどうかを確認する必要があります。問題は、送信から 4 日以内にバウンスを制限して、間違った送信がバウンスに一致しないようにする必要があることです。送信レコードは 30 日間にわたって分散されます。

LinkedList<event_data> sent = GetMyHugeListOfSends(); //for example 1M+ records
List<event_data> bounced = GetMyListOfBounces(); //for example 150k records

bounced = bounced.OrderBy(o => o.event_date).ToList(); //this ensures the most accurate match of bounce to send (since we find the first match)

List<event_data> delivered = new List<event_data>();
event_data deliveredEmail = new event_data();

foreach (event_data sentEmail in sent)
{

     event_data bounce = bounced.Find(item => item.email.ToLower() == sentEmail.email.ToLower() && (item.event_date > sentEmail.event_date && item.event_date < sentEmail.event_date.AddDays(deliveredCalcDelayDays)));

     //create delivered records
     if (bounce != null)
     {
          //there was a bounce! don't add a delivered record!
     }
     else
     {
          //if sent is not bounced, it's delivered
          deliveredEmail.sid = siteid;
          deliveredEmail.mlid = mlid;
          deliveredEmail.mid = mid;
          deliveredEmail.email = sentEmail.email;
          deliveredEmail.event_date = sentEmail.event_date;
          deliveredEmail.event_status = "Delivered";
          deliveredEmail.event_type = "Delivered";
          deliveredEmail.id = sentEmail.id;
          deliveredEmail.number = sentEmail.number;
          deliveredEmail.laststoretransaction = sentEmail.laststoretransaction;

          delivered.Add(deliveredEmail);   //add the new delivered
          deliveredEmail = new event_data();

          //remove bounce, it only applies to one send!
          bounced.Remove(bounce);
     }

     if (bounced.Count() == 0)
     {
          break; //no more bounces to match!
     }
}

そこで、いくつかのテストを行ったところ、1 秒あたり約 12 件の送信レコードを処理しています。100 万以上のレコードでは、処理に 25 時間以上かかります!

2 つの質問:

  1. 最も時間がかかっている正確な行を見つけるにはどうすればよいですか?
  2. 私は、これをそこに入れる前ははるかに速かったので、最も長くかかっているバウンスを見つけるラムダ式であると想定しています。どうすればこれをスピードアップできますか?

ありがとう!

編集

---アイデア---

  1. 私が思いついたアイデアの 1 つは、バウンスの場合と同じように送信を日付で並べ替えることです。これにより、バウンスの検索がより効率的になります。早期の送信は早期のバウンスにもヒットする可能性が高いためです。
  2. 私が思いついたもう 1 つのアイデアは、これらのプロセスのいくつかを並行して実行することです。ただし、この単純なアプリケーションをマルチスレッド化するのは好ましくありません。
4

7 に答える 7

0

私が見つけた最終的な解決策は、バウンスの辞書でした。

送信された LinkedList は sent_date でソートされているため、時系列でループします。正しいセンドと正しいバウンスを一致させる必要があるため、これは重要です。

を作成したので、キーは電子メールで、値は電子メール アドレスのすべてのバウンスDictionary<string,<List<event_data>>のリストでした。<event_data>最初のバウンスが送信と一致していることを確認したかったので、リストは event_date でソートされました。

最終結果... 700 レコード/分から 500k+ レコード/秒に処理されました。

最終的なコードは次のとおりです。

LinkedList sent = GetMyHugeListOfSends(); IEnumerable sentOrdered = sent.OrderBy(send => send.event_date);

Dictionary> バウンス = GetMyListOfBouncesAsDictionary();

リスト配信 = new List(); event_data deliveryEmail = new event_data();

リスト バウンス = null; bool matchingBounce = false;

foreach (event_data sentEmail in sentOrdered) {matchedBounce = false;

 //create delivered records
 if (bounced.TryGetValue(sentEmail.email, out bounces))
 {
      //there was a bounce! find out if it was within 4 days after the send!
      foreach (event_data bounce in bounces)
      {
           if (bounce.event_date > sentEmail.event_date &&
               bounce.event_date <= sentEmail.event_date.AddDays(4))
           {
               matchedBounce = true;

               //remove the record because a bounce can only match once back to a send
               bounces.Remove(bounce);

               if(bounces.Count == 0) //no more bounces for this email
               {
                    bounced.Remove(sentEmail.email);
               }

               break;
          }
     }

     if (matchedBounce == false) //no matching bounces in the list!
     {
          //if sent is not bounced, it's delivered
          deliveredEmail.sid = siteid;
          deliveredEmail.mlid = mlid;
          deliveredEmail.mid = mid;
          deliveredEmail.email = sentEmail.email;
          deliveredEmail.event_date = sentEmail.event_date;
          deliveredEmail.event_status = "Delivered";
          deliveredEmail.event_type = "Delivered";
          deliveredEmail.id = sentEmail.id;
          deliveredEmail.number = sentEmail.number;
          deliveredEmail.laststoretransaction = sentEmail.laststoretransaction;

          delivered.Add(deliveredEmail);   //add the new delivered
          deliveredEmail = new event_data();
     }
 }
 else
 {
      //if sent is not bounced, it's delivered
      deliveredEmail.sid = siteid;
      deliveredEmail.mlid = mlid;
      deliveredEmail.mid = mid;
      deliveredEmail.email = sentEmail.email;
      deliveredEmail.event_date = sentEmail.event_date;
      deliveredEmail.event_status = "Delivered";
      deliveredEmail.event_type = "Delivered";
      deliveredEmail.id = sentEmail.id;
      deliveredEmail.number = sentEmail.number;
      deliveredEmail.laststoretransaction = sentEmail.laststoretransaction;

      delivered.Add(deliveredEmail);   //add the new delivered
      deliveredEmail = new event_data();
 }

 if (bounced.Count() == 0)
 {
      break; //no more bounces to match!
 }
}
于 2013-05-23T22:25:50.520 に答える