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)); } } }
댓글 없음:
댓글 쓰기