c#에서 데이터테이블 병합 테스트를 수행하는 코드이다. 결과는 단순히 데이터테이블에 기본키(PK)만으로 병합을 수행할때 보다, lock과 병렬처리를 수행하면 2배 정도 속도가 향상된다. 또한 postgress 서버에서 FULL OUTER JOIN과 비교한 경우, postgress 에서 약 40초에 수행되면, 최고로 끌어 올린 병합 테스트에서는 약 60초이면 수행된다(일반 노트북 PC).
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataTableMergeTest
{
class DataTableMerge
{
public void DemonstrateMergeTable()
{
DataTable table1 = new DataTable("Items");
DataTable table2 = new DataTable("Items");
// Add columns
table1.Columns.Add(new DataColumn("id", typeof(System.Int32)));
table2.Columns.Add(new DataColumn("id", typeof(System.Int32)));
List<object> vls = new List<object>() { -1};
List<object> vls2 = new List<object>() { -1 };
for (int i = 0; i < 600; i++)
{
table1.Columns.Add(String.Format("item{0:D3}", i + 1));
vls.Add(String.Format("item value{0:D3}", i + 1));
if (i < 100)
{
table2.Columns.Add(String.Format("clone{0:D3}", i + 1));
vls2.Add(String.Format("clone value{0:D3}", i + 1));
}
}
table1.PrimaryKey = new DataColumn[] { table1.Columns["id"] };
table2.PrimaryKey = new DataColumn[] { table2.Columns["id"] };
object[] arr1 = vls.ToArray();
object[] arr2 = vls2.ToArray();
//table1.BeginLoadData();
//table2.BeginLoadData();
for (int i = 0; i < 100000; i++)
{
arr1[0] = i;
table1.Rows.Add(arr1);
arr2[0] = i;
table2.Rows.Add(arr2);
}
//table1.EndLoadData();
//table2.EndLoadData();
table1.AcceptChanges();
table2.AcceptChanges();
//===========================================================
DataTable dt = table1.Copy();
Stopwatch sw = Stopwatch.StartNew();
sw.Start();
object padlock = new object();
lock (padlock) // Makes sure only one merge operation is done at a time
{
dt.Merge(table2);
}
sw.Stop();
Console.WriteLine(String.Format("600 << 100 머지: {0} s", sw.ElapsedMilliseconds/1000.0));
//===========================================================
dt = table2.Copy();
sw = Stopwatch.StartNew();
sw.Start();
lock (padlock) // Makes sure only one merge operation is done at a time
{
dt.Merge(table1);
}
sw.Stop();
Console.WriteLine(String.Format("100 << 600 머지: {0} s", sw.ElapsedMilliseconds / 1000.0));
//===========================================================
dt = table2.Copy();
sw = Stopwatch.StartNew();
sw.Start();
dt.Merge(table1.Clone(), false, MissingSchemaAction.Add);
lock (padlock) // Makes sure only one merge operation is done at a time
{
List<DataTable> splites = new List<DataTable>();
for(int i = 0; i < table1.Rows.Count; i += 10000)
splites.Add(table1.AsEnumerable().Skip(0).Take(10000).CopyToDataTable());
Parallel.ForEach(splites.AsEnumerable(), src =>
{
dt.Merge(src);
});
}
sw.Stop();
Console.WriteLine(String.Format("100 << 600 Parallel.ForEach: {0} s", sw.ElapsedMilliseconds / 1000.0));
}
}
}
댓글 없음:
댓글 쓰기