【问题标题】:Takes long time to insert rows in SQL Server 2008 R2在 SQL Server 2008 R2 中插入行需要很长时间
【发布时间】:2025-11-22 22:30:02
【问题描述】:

我在 c# Winforms gridview 中有超过 200,000 条记录,插入我的数据库大约需要一个小时。我正在尝试提高此插入的性能。我希望在 5 到 10 分钟内插入所有记录。

我正在使用For 循环填充每一行以使用 SQL 事务插入数据库,我认为SqlBulkCopy 不会成功,因为之前需要使用数据库验证所有 200,000 条记录插入数据库。

     Save-Function:
     if (chkretailprice.Checked)
        {
                    DataTable dt_grid = (DataTable)gcPromotion.DataSource;
                    dt_grid.AcceptChanges();

                    for (int tt = 0; tt < gvPromotion.RowCount; tt++)
                    {
                        gvPromotion.FocusedRowHandle = tt;
                        double dRGridMinus = Convert.ToDouble(gvPromotion.GetRowCellValue(tt, gvPromotion.Columns["PromotionalRetailPrice"]));
                        string sItem = Convert.ToString(gvPromotion.GetRowCellValue(tt, gvPromotion.Columns["ItemName"]).ToString());
                        string sPack = Convert.ToString(gvPromotion.GetRowCellValue(tt, gvPromotion.Columns["Package"]).ToString());

                        if (dRGridMinus < 0)
                        {
                            gvPromotion.FocusedRowHandle = tt;
                            MessageBoxInfo("Promotional RetailPrice contains Negative Values for this ItemName-'" + sItem + "' & Package-'" + sPack + "'");
                            gvPromotion.Focus();
                            return;
                        }
                    }
                    int iReCount = dt_grid.Select("PromotionalRetailPrice='0.00'").Length;

                    if (iReCount != 0)
                    {
                        MessageBoxInfo("Promotional RetailPrice Must not be 0");
                        gvPromotion.Focus();
                        return;
                    }
       }
      if (rgPromotion.Checked)
         {
                        for (int p = 0; p < gvPromotion.RowCount; p++)
                        {
                            string[] sbranchArr = sBranchIDs.Split(',');
                            for (int pp = 0; pp < sbranchArr.Length; pp++)
                            {
                                objProEntity.PromotionMasterId = objProEntity.PromotionMasterId;
                                objProEntity.BranchId = Convert.ToInt32(sbranchArr[pp]);//gvPromotion.GetRowCellValue(p, gvPromotion.Columns["BranchID"]));
                                objProEntity.ItemId = Convert.ToInt64(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ItemID"]));
                                objProEntity.PackId = Convert.ToInt32(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PackTypeID"]));
                                objProEntity.PromotionValueType = Convert.ToString(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionValueType"]));
                                objProEntity.PromotionValue = Convert.ToString(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionValue"]));

                                if (chkretailprice.Checked && chkwholesaleprice.Checked)// when both retailprice & wholesaleprice checkbox is checked
                                {
                                    objProEntity.ActualRetailPrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualRetailPrice"]));
                                    objProEntity.PromoRetailPrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionalRetailPrice"]));
                                    objProEntity.ActualWholeSalePrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualWholeSalePrice"]));
                                    objProEntity.PromoWholesalePrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionalWholeSalePrice"]));
                                }
                                else if (chkretailprice.Checked)// when retailprice checkbox is checked
                                {

                                    objProEntity.ActualRetailPrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualRetailPrice"]));
                                    objProEntity.PromoRetailPrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionalRetailPrice"]));
                                    objProEntity.ActualWholeSalePrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualWholeSalePrice"]));
                                    objProEntity.PromoWholesalePrice = Convert.ToDecimal(0);
                                }
                                else if (chkwholesaleprice.Checked)// when wholesaleprice checkbox is checked
                                {
                                    objProEntity.ActualRetailPrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualRetailPrice"]));
                                    objProEntity.PromoRetailPrice = Convert.ToDecimal(0);
                                    objProEntity.ActualWholeSalePrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["ActualWholeSalePrice"]));
                                    objProEntity.PromoWholesalePrice = Convert.ToDecimal(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionalWholeSalePrice"]));
                                }
                                objProEntity.DiscountAllowed = Convert.ToBoolean(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["DiscountAllowed"]));

                                DataTable dt_Check = new DataTable();
                                dt_Check = SalesPromotionData.IsCheckItemExists(objProEntity, SQLTrans);                                    
                                if (dt_Check.Rows.Count == 0)
                                {
                                    if (!IsEdit)
                                    {
                                        DataTable dt_child = SalesPromotionData.InsertChildData(objProEntity, SQLTrans); // Insert Child Details when isEdit=false
                                    }
                                    else
                                    {
                                        if (gvPromotion.Columns.Contains(gvPromotion.Columns["PromotionChildId"]))
                                            if ((DBNull.Value.Equals(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionChildId"]))) || (gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionChildId"]) == "") || Convert.ToString(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionChildId"]).ToString()) == "0")
                                            {
                                                objProEntity.PromotionMasterId = masterid;
                                                SalesPromotionData.InsertChildData(objProEntity, SQLTrans);// insert child details when isEdit=true
                                            }
                                            else
                                            {
                                                objProEntity.PromotionChildId = Convert.ToInt64(gvPromotion.GetRowCellValue(p, gvPromotion.Columns["PromotionChildId"]).ToString());
                                                SalesPromotionData.UpdateChildDetails(objProEntity, SQLTrans); // update child details when isEdit=true
                                            }
                                        else
                                        {
                                            objProEntity.PromotionMasterId = masterid;
                                            SalesPromotionData.InsertChildData(objProEntity, SQLTrans);// insert child details when isEdit=true
                                        }
                                    }
                                }
                            }
                        }
    }

【问题讨论】:

  • 您似乎使用的是经典的 RBAR 方法。难怪需要很长时间。为什么不能在数据库中进行验证?然后你也许可以做一个批量插入
  • 200,000 行应该可以在几秒钟或更短的时间内插入。你能显示你正在使用的代码吗?
  • 数据库在做什么验证?为什么它不能同时验证所有 200k 行?您可以将列映射与 Bulk Copy 一起使用,以有效地将它们插入 SQL Server:*.com/a/20108861/2538939
  • 不,我无法在 db 中进行验证,因为每个网格行都经过验证以达到特定条件
  • @pradeepS 这些条件是什么?唯一性、排序等。

标签: c# sql sql-server sql-server-2008-r2


【解决方案1】:

通常,您会通过将数据批量插入到 [a] 工作表中来将数据暂存到数据库中,没有参照完整性或任何东西——只有原始数据加上您可能会用到的任何 [非唯一] 索引需要。完成后,您可以:

  • 根据您的数据库验证工作表中的数据并
  • 将其应用于有问题的“真实”表格。

【讨论】:

  • 是的,这也是我的看法。在“原始表”中根本没有索引甚至更好,因为每个索引都会减慢插入速度。此外,您如何处理被拒绝的记录。最好将所有内容快速加载到原始表中,然后在数据库引擎中进行进一步处理。
最近更新 更多