Хранимая процедура SQL Server приостанавливает каждые 75 записей из C # SqlClient - PullRequest
0 голосов
/ 02 июля 2019

У меня есть хранимая процедура, которая в основном выбирает из сложного представления, объединенного с несколькими другими столбцами.При запуске хранимой процедуры через SSMS требуется около 6 секунд, чтобы вернуть пару тысяч строк, но запуск ее с точно такими же параметрами из C # занимает более минуты.

Я добавил ведение журнала, когда он извлекал каждую запись,и кажется, что он извлекает 75 записей почти одновременно, а затем сидит там, ничего не делая в течение приблизительно 1,5 секунд, затем еще 75 строк.Точнее говоря, он приостанавливается каждый раз, когда достигает 74 по модулю 75, то есть 74, 149, 224 и т. Д. Задержки варьируются от 1,2 до 1,8 секунд.

Далее я вставил запрос из хранимой процедуры прямо вкод C #, и задержки ушли.При использовании встроенного SQL вместо хранимой процедуры запуск занимает всего 6 секунд.

Задержки кажутся очень странными и совершенно загадочными.Это не просто «этот запрос плохо оптимизирован в этой ситуации» или «слишком много данных».Ни один из данных не поступает с постоянными приращениями 3, 5, 15 или 75 с.Ни одно из полей не должно превышать 30 символов, нет полей varbinary (max) или varchar (max), всего 12 полей и около 2500 записей.Единственная причина, по которой при правильных условиях это занимает 6 секунд, заключается в том, что представление в SQL настолько сложное, а не потому, что оно перегружено, отправляя обратно огромные объемы данных.

Может быть, все следующие детали не имеют отношения к вопросу,Я в основном включаю их, чтобы прояснить, что нет ничего необычного ни в одном из задействованных кодов.

Вот общий обзор того, что делает код C # (ничего особенного):

using (var cmd = connection.CreateCommand())
{
    cmd.CommandText = "myprocedure";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@startValue", SqlDbType.NVarChar).Value = DBNull.Value;
    cmd.Parameters.Add("@endValue", SqlDbType.NVarChar).Value = DBNull.Value;
    var result = new List<MyObject>();
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            var myObj = new MyObject();
            myObj.Value1 = reader["Value1"] as string;
            myObj.Value2 = reader["Value2"] as int?;
            myObj.Value3 = reader["Value3"] as decimal?;
            result.Add(myObj);
        }
    }
    return result;
}

На практике реальный код немного сложнее, потому что он использует отражение в первый раз, когда его вызывают для создания установщиков для каждого из устанавливаемых полей:

(PropertyInfo property) =>
{
var param1 = Expression.Parameter(typeof(t));
var param2 = Expression.Parameter(typeof(object));
return Expression.Lambda<Action<t, object>>(
    Expression.Call(
        Expression.Convert(param1, property.ReflectedType),
        property.GetSetMethod(false),
        Expression.Convert(param2, property.PropertyType)),
    param1, param2).Compile();
}

Но я уверен, что это непроблема с этими установщиками, потому что код C # используется очень широко, и это единственный вызов базы данных, где происходит эта 1,5-секундная задержка.

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

DECLARE @startValue varchar(20) = NULL
DECLARE @endValue varchar(20) = NULL

SELECT MyView.*, OtherTable.Name
FROM MyView
INNER JOIN OtherTable ON MyView.PK = OtherTable.PK
WHERE (MyView.Value3 > 0 OR MyView.Value4 > 0)
AND (@startValue IS NULL OR MyView.Value1 >= @startValue)
AND (@endValue IS NULL OR MyView.Value1 <= @endValue)

Что может быть причиной задержки ~ 1,5 секунды в читателе evровно 75 записей?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...