Added another benchmark for removing/re-inserting records for cmsContentXml table using one transaction which again improves performance. Now have changed the rebuild xml method in the content service to : Lookup all data that it needs to insert first, then we begin a transaction and inside of the one transaction we clear the data and re-insert it so if anything fails in this process it should be rolled back.
This commit is contained in:
@@ -39,39 +39,47 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
using (var tr = db.GetTransaction())
|
||||
{
|
||||
try
|
||||
db.BulkInsertRecords(collection, tr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection, Transaction tr)
|
||||
{
|
||||
//don't do anything if there are no records.
|
||||
if (collection.Any() == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
|
||||
//SqlCe doesn't support bulk insert statements!
|
||||
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
//SqlCe doesn't support bulk insert statements!
|
||||
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
db.Insert(poco);
|
||||
}
|
||||
|
||||
db.Insert(poco);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] sqlStatements;
|
||||
var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements);
|
||||
for (var i = 0; i < sqlStatements.Length; i++)
|
||||
{
|
||||
string[] sqlStatements;
|
||||
var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements);
|
||||
for (var i = 0; i < sqlStatements.Length; i++)
|
||||
using (var cmd = cmds[i])
|
||||
{
|
||||
using (var cmd = cmds[i])
|
||||
{
|
||||
cmd.CommandText = sqlStatements[i];
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
cmd.CommandText = sqlStatements[i];
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.Complete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
tr.Dispose();
|
||||
throw;
|
||||
}
|
||||
tr.Complete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
tr.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1378,41 +1378,46 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
if (contentTypeIds.Any() == false)
|
||||
{
|
||||
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
|
||||
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
|
||||
//First we're going to get the data that needs to be inserted before clearing anything, this
|
||||
//ensures that we don't accidentally leave the content xml table empty if something happens
|
||||
//during the lookup process.
|
||||
|
||||
list.AddRange(GetAllPublished());
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var id in contentTypeIds)
|
||||
{
|
||||
//first we'll clear out the data from the cmsContentXml table for this type
|
||||
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
|
||||
(select cmsDocument.nodeId from cmsDocument
|
||||
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
|
||||
where published = 1 and contentType = @contentTypeId)", new {contentTypeId = id});
|
||||
|
||||
//now get all published content objects of this type and add to the list
|
||||
list.AddRange(GetPublishedContentOfContentType(id));
|
||||
}
|
||||
}
|
||||
list.AddRange(contentTypeIds.Any() == false
|
||||
? GetAllPublished()
|
||||
: contentTypeIds.SelectMany(GetPublishedContentOfContentType));
|
||||
|
||||
var xmlItems = new List<ContentXmlDto>();
|
||||
foreach (var c in list)
|
||||
{
|
||||
//generate the xml
|
||||
var xml = c.ToXml();
|
||||
//create the dto to insert
|
||||
xmlItems.Add(new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) });
|
||||
xmlItems.Add(new ContentXmlDto {NodeId = c.Id, Xml = xml.ToString(SaveOptions.None)});
|
||||
}
|
||||
//bulk insert it into the database
|
||||
uow.Database.BulkInsertRecords(xmlItems);
|
||||
|
||||
//Ok, now we need to remove the data and re-insert it, we'll do this all in one transaction too.
|
||||
using (var tr = uow.Database.GetTransaction())
|
||||
{
|
||||
if (contentTypeIds.Any() == false)
|
||||
{
|
||||
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
|
||||
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var id in contentTypeIds)
|
||||
{
|
||||
//first we'll clear out the data from the cmsContentXml table for this type
|
||||
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
|
||||
(select cmsDocument.nodeId from cmsDocument
|
||||
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
|
||||
where published = 1 and contentType = @contentTypeId)", new { contentTypeId = id });
|
||||
}
|
||||
}
|
||||
|
||||
//bulk insert it into the database
|
||||
uow.Database.BulkInsertRecords(xmlItems, tr);
|
||||
}
|
||||
}
|
||||
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
|
||||
}
|
||||
|
||||
@@ -211,6 +211,27 @@ namespace Umbraco.Tests.Services
|
||||
}
|
||||
}
|
||||
|
||||
//now, test truncating but then do bulk insertion of records
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + bulk insert test in one transaction"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//now we insert each record for the ones we've deleted like we do in the content service.
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
|
||||
|
||||
using (var tr = DatabaseContext.Database.GetTransaction())
|
||||
{
|
||||
//clear all the xml entries
|
||||
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
|
||||
|
||||
|
||||
DatabaseContext.Database.BulkInsertRecords(xmlItems, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user