【问题标题】:Generating and inserting large amount of data into MS SQL from WCF从 WCF 生成大量数据并将其插入 MS SQL
【发布时间】:2013-04-29 07:04:59
【问题描述】:

我的任务是生成大约 1'000'000 行并将其插入到 2 个表中。困难是我必须插入现有的外键,所以我先从其他表中获取数据...... 而不是我尝试生成具有 1000000 行的新 DataTable 以将其粘贴到 SqlBulk... 但是这代需要太长时间(每分钟约 4000 行!)这是代码,也许有人可以帮助优化它...

public void GenerateData(DateTime fromDate, DateTime toDate, int Size)
    {
        DataTable theDatetime = new DataTable();
        theDatetime.Columns.Add("Datetime", new DateTime().GetType());
        theDatetime.Columns.Add("Date", new DateTime().GetType());
        theDatetime.Columns.Add("Hour", new Int32().GetType());
        DataTable theOverspeed = new DataTable();
        theOverspeed.Columns.Add("CarNumber", new Int32().ToString().GetType());
        theOverspeed.Columns.Add("Datetime", new DateTime().GetType());
        theOverspeed.Columns.Add("DistrictCode", new Int32().GetType());
        theOverspeed.Columns.Add("MarkCode", new Int32().GetType());
        theOverspeed.Columns.Add("OwnerCode", new Int32().GetType());
        theOverspeed.Columns.Add("RecognitorNumber", new Int32().GetType());
        theOverspeed.Columns.Add("Region", new Int32().GetType());
        theOverspeed.Columns.Add("RouteCode", new Int32().GetType());
        theOverspeed.Columns.Add("Overspeed", new Int32().GetType());
        theOverspeed.Columns.Add("Speed", new Int32().GetType());
        Dictionary<DateTime, DateTime> Dates = new Dictionary<DateTime, DateTime>();
        Random TheGenerator = new Random();
        DataTable theCars = getCars();
        DataTable theRecognitors = getRecognitors();
        int[] sizes = new int[5];
        for(int step = 0; step < 5; ++step)
        {
            DateTime Current1 = GetFifthDate(fromDate, toDate)[step];
            DateTime Current2 = GetFifthDate(fromDate, toDate)[step+1];
            int CurrentCount = GetFifthCount(Size)[step];
            for (int i = 0; i < CurrentCount; ++i)
            {
                var aDate = GetRandomDate(Current1, Current2);
                if (!Dates.ContainsKey(aDate))
                {
                    InsertFact(theCars, aDate, theRecognitors,
                        theDatetime, theOverspeed);
                    Dates.Add(aDate, aDate);
                }
                else
                {
                    i--;
                }
            }

        }

InsertFact 方法

private void InsertFact(DataTable theCars,
        DateTime theDate,
        DataTable theRecognitor, DataTable theDatetime, DataTable theOverspeed)
    {
        Random theGenerator = new Random(DateTime.Now.Millisecond);
        DataRow rowDate = theDatetime.NewRow();
        rowDate["DateTime"] = theDate;
        rowDate["Date"] = theDate.Date;
        rowDate["Hour"] = theDate.Hour;
        theDatetime.Rows.Add(rowDate);
        int car = theGenerator.Next(theCars.Rows.Count);
        int recognitor = theGenerator.Next(theRecognitor.Rows.Count);
        DataRow rowOverspeed = theOverspeed.NewRow();
        rowOverspeed["CarNumber"] = theCars.Rows[car][4];
        rowOverspeed["Datetime"] = theDate;
        rowOverspeed["DistrictCode"] = theRecognitor.Rows[recognitor][3];
        rowOverspeed["MarkCode"] = theCars.Rows[car][3];
        rowOverspeed["OwnerCode"] = theCars.Rows[car][2];
        rowOverspeed["RecognitorNumber"] = theRecognitor.Rows[recognitor][2];
        rowOverspeed["Region"] = theCars.Rows[car][1];
        rowOverspeed["RouteCode"] = theRecognitor.Rows[recognitor][1];
        rowOverspeed["Overspeed"] = theGenerator.Next(10, 40);
        rowOverspeed["Speed"] = theGenerator.Next(100) > 40 ? 70 : 90;
        theOverspeed.Rows.Add(rowOverspeed);}

获取识别器

private DataTable getRecognitors()
    {
        DataTable Result = new DataTable("Recognitors");
        using (SqlConnection theConnection = new SqlConnection(str))
        {
            theConnection.Open();
            SqlDataAdapter theAdapter = new SqlDataAdapter();
            SqlCommand theCommand = new SqlCommand("Select * from Recognitor", theConnection);
            theCommand.CommandType = System.Data.CommandType.Text;
            theCommand.CommandTimeout = 0;
            theAdapter.SelectCommand = theCommand;
            theAdapter.Fill(Result);
        }
        return Result;
    }

获取汽车

private DataTable getCars()
    {
        DataTable Result = new DataTable("Cars");
        using (SqlConnection theConnection = new SqlConnection(str))
        {
            theConnection.Open();
            SqlDataAdapter theAdapter = new SqlDataAdapter();
            SqlCommand theCommand = new SqlCommand("Select * from Car", theConnection);
            theCommand.CommandType = System.Data.CommandType.Text;
            theCommand.CommandTimeout = 0;
            theAdapter.SelectCommand = theCommand;
            theAdapter.Fill(Result);
        }            
        return Result;
    }

【问题讨论】:

  • new DateTime().GetType() => typeof(DateTime), new Int32().GetType() => typeof(int), new Int32().ToString().GetType() => typeof(string) -> 伙计,你成就了我的一天。另外,请出示getCarsgetRecognitors 代码。
  • 对不起,我的 c# 技能很差,这是我的第一个项目......
  • 您为什么不在 SQL 中执行此操作?一般要快很多。你还需要随机日期吗?您不能将日期时间增加 1 秒而不是随机 -> 检查是否已使用等...
  • 我必须从 WCF 生成这一代,这是任务的一部分......如果有一种方法可以生成 sqlScript,它将用随机值填充数据库......我会很高兴使用它...
  • @LeYar 我建议看看这个网站:it.toolbox.com/blogs/db2luw/…。它解释了在 SQL 中使用随机数据生成插入语句所需知道的一切。

标签: c# sql wcf datatable


【解决方案1】:

在我看来,您的代码有太多空闲通道,并且在数据生成期间它们的数量会增加。看看这两行:

for (int i = 0; i < CurrentCount; ++i)
{
    var aDate = GetRandomDate(Current1, Current2);
    if (!Dates.ContainsKey(aDate))
    {
        // insert
    }
    else
    {
        i--;
    }
}

您生成的数据越多,条件Dates.ContainsKey 评估为真的次数就越多。由于生成数字的正态分布,生成唯一数字所需的时间以非线性方式增加。

您绝对应该修改用于日期生成的方法。

附: Dictionary&lt;DateTime, DateTime&gt; Dates => HashSet&lt;DateTime&gt;.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    相关资源
    最近更新 更多