EF ObjectContext (db-first) を使用して、多数の行 (>10,000,000) を MySQL データベースに挿入しようとしています。この質問の回答を読んだ後、 約 10,000 件の連絡先 (実際には 30,000 行、関連する他の行を含む) を挿入するために、このコード (バッチ保存) を書きました。
// var myContactGroupId = ...;
const int maxContactToAddInOneBatch = 100;
var numberOfContactsAdded = 0;
// IEnumerable<ContactDTO> contacts = ...
foreach (var contact in contacts)
{
var newContact = AddSingleContact(contact); // method excerpt below
if (newContact == null)
{
return;
}
if (++numberOfContactsAdded % maxContactToAddInOneBatch == 0)
{
LogAction(Action.ContactCreated, "Batch #" + numberOfContactsAdded / maxContactToAddInOneBatch);
_context.SaveChanges();
_context.Dispose();
// _context = new ...
}
}
// ...
private Contact AddSingleContact(ContactDTO contact)
{
Validate(contact); // Simple input validations
// ...
// ...
var newContact = Contact.New(contact); // Creates a Contact entity
// Add cell numbers
foreach (var cellNumber in contact.CellNumbers)
{
var existingContactCell = _context.ContactCells.FirstOrDefault(c => c.CellNo == cellNumber);
if (existingContactCell != null)
{
// Set some error message and return
return;
}
newContact.ContactCells.Add(new ContactCell
{
CellNo = cellNumber,
});
}
_context.Contacts.Add(newContact);
_context.ContactsInGroups.Add(new ContactsInGroup
{
Contact = newContact,
// GroupId = some group id
});
return newContact;
}
しかし、より多くの連絡先が追加されると(バッチごとに)、より多くの時間がかかるようです(非線形)。バッチ サイズ 100 (10,000 件の連絡先) のログを次に示します。バッチ番号が増加するにつれて、必要な時間が増加することに注意してください。
12:16:48 Batch #1
12:16:49 Batch #2
12:16:49 Batch #3
12:16:50 Batch #4
12:16:50 Batch #5
12:16:50 Batch #6
12:16:51 Batch #7
12:16:52 Batch #8
12:16:53 Batch #9
12:16:54 Batch #10
...
...
12:21:26 Batch #89
12:21:32 Batch #90
12:21:38 Batch #91
12:21:44 Batch #92
12:21:50 Batch #93
12:21:57 Batch #94
12:22:03 Batch #95
12:22:10 Batch #96
12:22:16 Batch #97
12:22:23 Batch #98
12:22:29 Batch #99
12:22:36 Batch #100
6分48秒かかりました。バッチ サイズを 10,000 に増やすと (1 つのバッチが必要)、約 26 秒かかります (10,000 の連絡先の場合)。しかし、100k の連絡先 (バッチごとに 10k) を挿入しようとすると、長い時間がかかります (バッチごとに増加する時間がかかると思います)。
コンテキストが更新されているにもかかわらず、時間がかかっている理由を説明できますか? 生の SQL 以外のアイデアはありますか?