简体   繁体   English

SQLServer:如何使用c#加快语句循环中的选择和插入查询

[英]SQLServer:How to speed up Select and Insert query in loops of statements using c#

I am trying to insert into table from array of Json as well as select records from SQL Server DB table. 我正在尝试从Json数组插入表中,以及从SQL Server DB表中选择记录。 When executing the below method it is almost taking more than 10 minutes. 执行以下方法时,几乎要花费10多分钟。

public async Task CreateTableAsync(string formsJson, string connectionString)
{
    SqlConnection con = new SqlConnection(connectionString);
    List<FormsJson> listOfformsJson = JsonConvert.DeserializeObject<List<FormsJson>>(formsJson);
    foreach (var form in listOfformsJson)
    {
        string formId = Guid.NewGuid().ToString();
        //insert into forms Table
        string formQuery = "insert into Forms([FormId]) values(@FormId)";
        using (var cmd = new SqlCommand(formQuery, con))
        {
            cmd.CommandTimeout = 120;
            //Pass values to Parameters
            cmd.Parameters.AddWithValue("@FormId", formId);
            if (con.State == System.Data.ConnectionState.Closed)
            {
                con.Open();
            }
            cmd.ExecuteNonQuery();
        }

        //relationship between forms and ETypes,get all the eTypes and fill
        foreach (var typeOf in form.TypeOf)
        {
            //get all the eTypeIds for this typeof field
            string query = "select Id from ETypes Where TypeOf = @typeOf";
            List<string> eTypeIdList = new List<string>();
            using (var sqlcmd = new SqlCommand(query, con))
            {
                sqlcmd.CommandTimeout = 120;
                //Pass values to Parameters
                sqlcmd.Parameters.AddWithValue("@typeOf", typeOf);
                if (con.State == System.Data.ConnectionState.Closed)
                {
                    con.Open();
                }
                SqlDataReader sqlDataReader = sqlcmd.ExecuteReader();
                while (sqlDataReader.Read())
                {
                    string eTypeId = sqlDataReader[0].ToString();
                    eTypeIdList.Add(eTypeId);
                }
                sqlDataReader.Close();
            }
            //insert into Forms ETypes Relationship
            string fe_query = "";
            foreach (var eTypeId in eTypeIdList)
            {
                fe_query = "insert into Forms_ETypes([Form_Id],[EType_Id]) values (@Form_Id,@EType_Id)";
                if (con.State == System.Data.ConnectionState.Closed)
                {

                    con.Open();
                }
                using (var fesqlcmd = new SqlCommand(fe_query, con))
                {
                    fesqlcmd.CommandTimeout = 120;
                    //Pass values to Parameters
                    fesqlcmd.Parameters.AddWithValue("@Form_Id", formId);
                    fesqlcmd.Parameters.AddWithValue("@EType_Id", eTypeId);
                    fesqlcmd.ExecuteNonQuery();
                }
            }
        }
    }
}

Outer foreach(...listofformsJson) loop more than hundreds of records. 外部foreach(... listofformsJson)循环了数百条记录。
And same for the inner loop around hundreds of rows. 对于数百行的内部循环也是如此。

In between commandTimeout, keeping the open connection with server statements. 在commandTimeout之间,保持与服务器语句的开放连接。 Any help to optimize the time and remove/add ADO statements. 任何有助于优化时间并删除/添加ADO语句的帮助。

The primary issue here is that you are pulling all of the data out of the database and then, row by row, inserting it back in. This is not optimal from the database's point of view. 这里的主要问题是,您要从数据库中提取所有数据,然后逐行将其重新插入。从数据库的角度来看,这并不是最佳选择。 It is great at dealing with sets - but you are treating the set as lots of individual rows. 它非常适合处理集合-但是您会将集合视为很多单独的行。 Thus it becomes slow. 因此它变得缓慢。

From a set-based standpoint, you have only two statements that you need to run: 从基于集合的角度来看,您只需要运行两个语句:

  1. Insert the Forms row 插入Forms
  2. Insert the Forms_ETypes rows (as a set, not one at a time) 插入Forms_ETypes行(作为一组,而不是一次插入)

1) should be what you have now: 1)应该是您现在拥有的:

insert into Forms([FormId]) values(@FormId)

2) should be something like: 2)应该是这样的:

insert Forms_ETypes([Form_Id],[EType_Id]) SELECT @FormId, Id from ETypes Where TypeOf IN ({0});

using this technique to pass in your form.TypeOf values. 使用此技术来传递form.TypeOf值。 Note this assumes you have fewer than 500 entries in form.TypeOf . 请注意,这假设您在form.TypeOf少于500个条目。 If you have many (eg greater than 500) then using a UDT is a better approach (note some info on UDTs suggest that you need to use a stored proc, but that isn't the case ). 如果您有很多(例如,大于500),那么使用UDT是更好的方法(请注意,有关UDT的一些信息建议您需要使用存储的proc,但事实并非如此 )。

This will enable you to run just two SQL statements - the first, then the second (vs possibly thousands with your current solution). 这将使您仅运行两个SQL语句-第一个,然后运行第二个(与当前解决方案可能成千上万个相比)。

This will save time for two reasons: 这将节省时间,原因有两个:

  1. The database engine didn't need to pass the data over the wire twice (from your DB server to your application, and back again). 数据库引擎不需要两次通过网络传递数据(从数据库服务器到应用程序,然后再传递一次)。
  2. You enabled the database engine to do a large set based operation, rather than lots of smaller operations (with latency due to the request-response nature of the loop). 您使数据库引擎能够执行基于大型集合的操作,而不是执行许多较小的操作(由于循环的请求-响应性质,因此具有延迟)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM