SQLServer: как ускорить процесс выбора и вставки запроса в циклах операторов с помощью c # - PullRequest
0 голосов
/ 27 октября 2018

Я пытаюсь вставить в таблицу из массива Json, а также выбрать записи из таблицы БД SQL Server.При выполнении описанного ниже метода это почти занимает более 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();
                }
            }
        }
    }
}

Внешний цикл foreach (... listofformsJson) более сотни записей.
И то же самое для внутреннего цикла вокруг сотенrow.

Между commandTimeout сохраняется открытое соединение с операторами сервера.Любая помощь для оптимизации времени и удаления / добавления операторов ADO.

1 Ответ

0 голосов
/ 28 октября 2018

Основной проблемой здесь является то, что вы извлекаете все данные из базы данных, а затем построчно вставляете их обратно. Это не оптимально с точки зрения базы данных.Он отлично справляется с множествами, но вы рассматриваете множество как множество отдельных рядов.Таким образом, это становится медленным.

С точки зрения набора, у вас есть только два оператора, которые вам нужно выполнить:

  1. Вставьте строку Forms
  2. Вставьте Forms_ETypes строк (как набор, а не по одному за раз)

1) должно быть то, что у вас сейчас:

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

2) должно быть что-то вроде:

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

с использованием этой техники для передачи ваших form.TypeOf значений.Обратите внимание, что предполагается, что у вас есть менее 500 записей в form.TypeOf.Если у вас их много (например, больше 500), тогда лучше использовать UDT (обратите внимание, что некоторая информация о UDT предполагает, что вам нужно использовать сохраненный процесс, но не соответствует действительности.).

Это позволит вам выполнить только два оператора SQL - первый, а затем второй (возможно, тысячи с вашим текущим решением).

Это сохранитвремя по двум причинам:

  1. Механизму базы данных не нужно было дважды передавать данные по проводам (с сервера БД на ваше приложение и обратно).
  2. Выразрешил ядру базы данных выполнять операции на основе большого набора, а не множество операций меньшего размера (с задержкой из-за характера цикла запрос-ответ).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...