浅谈使用SQLBulkCopy批量数据入库

随着网站浏览人数的增多,页面浏览日志的记录成了数据库TCP/IP连接数飙升的祸首,初步想法就是先把日志记录到内存,累计到一定数量时,一次性入库。故此,就想到了sqlbulkcopy,它可以使数据批量入库。Msdn对它的描述:使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到DataTable或者IDataReader实例读取数据。

写个控制台程序测试了一下,生成了100000条数据,入库时间大概1秒,不过,只用了两个字段,实际中不会有这么少的字段。

先建一测试表,

CREATE TABLE [dbo].[Person](

    [PersonId] [int] IDENTITY(1,1) NOT NULL,

    [Name] [nvarchar](100) NOT NULL,

    [DateOfBirth] [datetime] NULL,

    CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([PersonId] ASC)

)

初步构想就是把进来的数据首先放入一个队列中,达到一定数量时把数据放到DataTable中,当DataTable中的数据累计到一定数量时,调用SqlBulkCopy进行入库。

先写一工具类,

public static class Util

    {

        public static Queue<Person> persons = new Queue<Person>();

        private static DataTable dataPerson = null;

        private static readonly object obj = new object();

        public static DataTable DtPerson

        {

            get

            {

                if (dataPerson == null)

                {

                    lock (obj)

                    {

                        dataPerson = CreateTable();

                    }

                    return dataPerson;

                }

                return dataPerson;

            }

        }

        public static DataTable CreateTable()

        {

            DataTable dt = new DataTable();

            DataColumn dc = null;

            dc = new DataColumn();

            dc.ColumnName = "Name";

            dt.Columns.Add(dc);

            dc = new DataColumn();

            dc.ColumnName = "DateOfBirth";

            dt.Columns.Add(dc);

            return dt;

        }

    }

实体类的代码,

public class Person

    {

        public string Name { get; set; }

        public DateTime? DateOfBirth { get; set; }

    }

下面是Program类实现代码

class Program

    {

        static void Main(string[] args)

        {

            for (int i = 0; i < 100000; i++)

            {

                Util.persons.Enqueue(CreatePerson(i));

                Console.WriteLine(" enqueue:" + i.ToString());

                DataImportToDataTable();

            }

            Console.ReadLine();

        }

        public static void DataImportToDataTable()

        {

            if (Util.persons.Count >= 100)

            {

                for (int i = 0; i < 100; i++)

                {

                    //出对数据

                    Person p = Util.persons.Dequeue();

                    Console.WriteLine("Import Data To DataTable:" + p.Name.ToString());

                    //写入表中

                    DataRow dr = Util.DtPerson.NewRow();

                    dr["Name"] = p.Name;

                    dr["DateOfBirth"] = p.DateOfBirth;

                    Util.DtPerson.Rows.Add(dr);

                }

                Console.WriteLine("Dequeue count:" + Util.persons.Count);

            }      

            InsertTable(Util.DtPerson);

        }

        public static void InsertTable(DataTable dt)

        {

            //达到一定数量,进行入库

            if (dt.Rows.Count >= 1000)

            {

                using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString))

                {

                    //打开连接

                    cnn.Open();

                    using (SqlBulkCopy sbc = new SqlBulkCopy(cnn))

                    {

                        //Person为要插入数据的表

                        sbc.DestinationTableName = "Person";

                  //字段映射。如果dt中的字段数和数据库表中的字段数不一样多 一定要进行映射

                        sbc.ColumnMappings.Add("Name", "Name");

                        sbc.ColumnMappings.Add("DateOfBirth", "DateOfBirth");

                        //每次加载数据的行数。不设置默认为全部,在本例中就可以不设置

                        sbc.BatchSize = dt.Rows.Count;

                        Console.WriteLine("sqlbulkcopy begin:" + DateTime.Now);

                        try

                        {

                            sbc.WriteToServer(dt);

                        }

                        catch (Exception ex)

                        {

                            Console.WriteLine(ex.Message);

                        }

                        Console.WriteLine("sqlbulkcopy end:" + DateTime.Now);

                    }

                }

                lock (Util.DtPerson)

                {

                    Util.DtPerson.Clear();

                    Console.WriteLine("after clear:" + Util.DtPerson.Rows.Count);

                }

            }

        }

        public static Person CreatePerson(int id)

        {

            Person p = new Person

            {

                Name="Person"+id.ToString(),

                DateOfBirth = new DateTime(1950 + (id % 50), ((id * 3) % 12) + 1, ((id * 7) % 29) + 1)

            };

            return p;

        }

    }

posted @ 2011-08-17 14:55  秋无语  阅读(1032)  评论(3编辑  收藏  举报