c# 데이터테이블 병합 테스트

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));

        }
    }
}

댓글 없음:

댓글 쓰기