插入几行后,Sql server Insert变慢

时间:2018-02-01 15:03:02

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

我从web api在sql server 2008 R2中插入数据。大约有300条记录插入到3到4个表中。在几毫秒之后,可以轻松插入前20到30条记录,之后插入记录需要几秒到几分钟。 sql server安装在Windows Server 2012 R2中。

如果在插入后删除相同的记录,然后再次调用api插入相同的数据,则插入只需2到3秒。

这是api代码

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using ProductsApp.ApplicationLogics;
using System.Web.Http.Cors;
using Newtonsoft.Json;

namespace ProductsApp.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "POST")]
    public class DataPostController : ApiController
    {
        [AcceptVerbs("POST")]
        public string DataPost([FromBody] List<Models.ReadingData> model)
        {
            if (model == null)
            {
                return "Data not found!";
            }

            string sql, id1;
            string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["APIConnectionString"].ConnectionString;

            using (SqlConnection con = new SqlConnection(connectionString))
            {
                con.Open();

                using (SqlTransaction tran = con.BeginTransaction())
                {
                    foreach (var item in model)
                    {

                        sql = @"INSERT INTO TableA(Col1, Col2, Col3, Col4) 
                                SELECT @Col1, @Col2, @Col3, @Col4;
                                SELECT SCOPE_IDENTITY();";

                        using (SqlCommand sqlCommand = new SqlCommand(sql, con, tran))
                        {
                            sqlCommand.Parameters.AddWithValue("@Col1", item.value1);
                            sqlCommand.Parameters.AddWithValue("@Col2", item.value2);
                            sqlCommand.Parameters.AddWithValue("@Col3", item.value3);

                            try
                            {
                                id1 = Convert.ToString(sqlCommand.ExecuteScalar());


                                if (item.amount > 0)
                                {                                    
                                    if (item.something != "0")
                                    {
                                        sql = @"INSERT INTO TableB(Col1, Col2, Col3)
                                                    SELECT @Col1, @Col2, @Col3;";
                                        using (SqlCommand sqlCommand2 = new SqlCommand(sql, con, tran))
                                        {
                                            sqlCommand2.Parameters.AddWithValue("@Col1", id1);
                                            sqlCommand2.Parameters.AddWithValue("@Col2", item.value5);
                                            sqlCommand2.Parameters.AddWithValue("@FiscalYearId", item.value6);

                                            try
                                            {
                                                sqlCommand2.ExecuteNonQuery();
                                            }
                                            catch (SqlException ex)
                                            {
                                                tran.Rollback();
                                                return ex.Message;
                                            }
                                        }                                    
                                    }
                                }

                                if (item.advanceAmount > 0 || item.outstandingAmount > 0)
                                {
                                    sql = @"UPDATE CustomersInfo SET AdvanceAmount=0, OutstandingAmount=0 WHERE CustomerId=@CustomerId;
                                            UPDATE COAR SET IsClear=1 WHERE CustomerId=@CustomerId;
                                            INSERT INTO COAR(FiscalYearId, CustomerId, EntryByUserId, OutstandingAmount, AdvanceAmount) 
                                                SELECT @FiscalYearId, @CustomerId, @EntryByUserId, @OutstandingAmount, @AdvanceAmount;";
                                }
                                else
                                {
                                    sql = @"UPDATE CustomersInfo SET AdvanceAmount=0 WHERE CustomerId=@CustomerId;
                                                UPDATE COAR SET IsClear=1 WHERE CustomerId=@CustomerId;";
                                }

                                using (SqlCommand sqlCommand2 = new SqlCommand(sql, con, tran))
                                {
                                    sqlCommand2.Parameters.AddWithValue("@FiscalYearId", item.FiscalYearId);
                                    sqlCommand2.Parameters.AddWithValue("@CustomerId", item.CustomerId);
                                    sqlCommand2.Parameters.AddWithValue("@EntryByUserId", item.MeterReaderId);
                                    sqlCommand2.Parameters.AddWithValue("@OutstandingAmount", item.outstandingAmount);
                                    sqlCommand2.Parameters.AddWithValue("@AdvanceAmount", item.advanceAmount);

                                    try
                                    {
                                        sqlCommand2.ExecuteNonQuery();
                                    }
                                    catch (SqlException ex)
                                    {
                                        tran.Rollback();
                                        return ex.Message;
                                    }
                                }


                                /*Insert Spot Fine (if any)*/
                                if (item.Fine > 0)
                                {
                                    sql = @"INSERT INTO CreditSales(CreditSalesDateAD, CreditSalesDateBS, FiscalYearId, 
                                                CustomerId, ParticularsId, Amount, EntryByUserId, Status, MonthSN, MonthId)  
                                            SELECT @CreditSalesDateAD, @CreditSalesDateBS, @FiscalYearId, 
                                                @CustomerId, @ParticularsId, @Amount, @EntryByUserId, @Status, @MonthSN, @MonthId;";
                                    using (SqlCommand sqlCommand4 = new SqlCommand(sql, con, tran))
                                    {
                                        sqlCommand4.Parameters.AddWithValue("CreditSalesDateAD", item.meterReadingDateAD);
                                        sqlCommand4.Parameters.AddWithValue("CreditSalesDateBS", item.meterReadingDateBS);
                                        sqlCommand4.Parameters.AddWithValue("FiscalYearId", item.FiscalYearId);
                                        sqlCommand4.Parameters.AddWithValue("CustomerId", item.CustomerId);
                                        sqlCommand4.Parameters.AddWithValue("ParticularsId", 5); //Always will be 5
                                        sqlCommand4.Parameters.AddWithValue("Amount", item.Fine);
                                        sqlCommand4.Parameters.AddWithValue("EntryByUserId", item.MeterReaderId);
                                        sqlCommand4.Parameters.AddWithValue("Status", "0");
                                        sqlCommand4.Parameters.AddWithValue("MonthSN", item.monthSN);
                                        sqlCommand4.Parameters.AddWithValue("MonthId", item.MonthId);

                                        try
                                        {
                                            sqlCommand4.ExecuteNonQuery();
                                        }
                                        catch (SqlException ex)
                                        {
                                            tran.Rollback();
                                            return ex.Message;
                                        }
                                    }
                                }

                                /*If any tap repair complain*/
                                if (item.TapRepair == 1)
                                {
                                    sql = @"INSERT INTO TapRepairs(ComplainDateAD, ComplainDateBS, FiscalYearId, CustomerId, ComplainTypeId,
                                                        RepairDateAD, RepairDateBS, RepairDescription, RepairByUserId)
                                            SELECT @ComplainDateAD, @ComplainDateBS, @FiscalYearId, @CustomerId, @ComplainTypeId,
                                                        @RepairDateAD, @RepairDateBS, @RepairDescription, @RepairByUserId;";

                                    using (SqlCommand sqlCommand5 = new SqlCommand(sql, con, tran))
                                    {
                                        sqlCommand5.Parameters.AddWithValue("@ComplainDateAD", item.meterReadingDateAD);
                                        sqlCommand5.Parameters.AddWithValue("@ComplainDateBS", item.meterReadingDateBS);
                                        sqlCommand5.Parameters.AddWithValue("@FiscalYearId", item.FiscalYearId);
                                        sqlCommand5.Parameters.AddWithValue("@CustomerId", item.CustomerId);
                                        sqlCommand5.Parameters.AddWithValue("@ComplainTypeId", item.Remarks);
                                        sqlCommand5.Parameters.AddWithValue("@RepairDateAD", item.meterReadingDateAD);
                                        sqlCommand5.Parameters.AddWithValue("@RepairDateBS", "");
                                        sqlCommand5.Parameters.AddWithValue("@RepairDescription", "");
                                        sqlCommand5.Parameters.AddWithValue("@RepairByUserId", item.MeterReaderId);

                                        try
                                        {
                                            sqlCommand5.ExecuteNonQuery();
                                        }
                                        catch (SqlException ex)
                                        {
                                            tran.Rollback();
                                            return ex.Message;
                                        }
                                    }
                                }

                            }
                            catch (SqlException ex)
                            {
                                if (ex.Message.Contains("MeterReadingEntries_FYID_MID_CID"))
                                {
                                    //If meter reading entry already done
                                    continue;
                                }
                                else
                                {
                                    tran.Rollback();
                                    return ex.Message;
                                }
                            }
                        }
                    }

                    tran.Commit();
                    con.Close();
                    con.Dispose();
                }
            }

            return "ok";
        }
    }
}

每个表仅包含最多10列。 可能是什么原因? api有什么问题吗?为什么在删除并重新插入相同记录后插入速度很快?

更新: Profiler图片 Profiler Attached Image

1 个答案:

答案 0 :(得分:0)

除了创建存储过程并将批处理发送到存储过程之外,我肯定会补充一点,即每个循环中每个查询的执行计划可能不同。

这篇文章已经解决了这个问题: SQL Query slow in .NET application but instantaneous in SQL Server Management Studio

看看erikkallen写的答案