ADO.Net: повторно использовать SqlConnection или каждый раз получать новый?

Прежде чем отправлять этот вопрос, я прочитал несколько ответов на этом сайте: этого . Все, похоже, согласны с тем, что «пулы приложений C# оптимизированы для нескольких вызовов в одну и ту же базу данных».

Тем не менее, я по-прежнему наблюдаю существенное снижение производительности, если получаю соединение из пула. Вот мои ориентиры:

    private const string localConnString = "Data Source=(local);Integrated Security=SSPI;database=MyTest;Pooling=true";


    [Test]
    public void GetNewConnectionEveryTime()
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < 1000; i++)
        {
            using (var conn = new SqlConnection(localConnString))
            {
                conn.Open();
                const string saveTrancount = "EXEC dbo.TestTran";
                ExecuteSql(conn, saveTrancount);
            }
        }
        stopwatch.Stop();
        Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
        //Time elapsed: 00:00:00.5576016
    }

    [Test]
    public void ReuseOneConnection()
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        using (var conn = new SqlConnection(localConnString))
        {
            conn.Open();
            for (var i = 0; i < 1000; i++)
            {
                const string saveTrancount = "EXEC dbo.TestTran";
                ExecuteSql(conn, saveTrancount);
            }
        }
        stopwatch.Stop();
        Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
        //Time elapsed: 00:00:00.1110324
    }

    private void ExecuteSql(SqlConnection conn, string sql, int timeout = 0)
    {
        var command = conn.CreateCommand();
        command.CommandText = sql;
        command.CommandType = CommandType.Text;
        command.CommandTimeout = timeout;
        command.ExecuteNonQuery();
    }

Очевидно, что получение соединения из пула занимает в четыре раза больше времени (00: 00: 00.5576016 - 00: 00: 00.1110324 appr 0.44), чем выполнение фактической работы (00: 00: 00.1110324 во втором эталоном). Что мне не хватает?

Изменить: Я запускаю эти тесты против базы данных, созданной на RAM Disk, поэтому все мои операции с базой данных выполняются очень быстро.

4
добавлено отредактировано
Просмотры: 2
nl ja de

2 ответы

Тебе нужны тесты. Было бы еще хуже, если бы вы открыли и закрыли соединение для каждой итерации без объединения пулов, но это совсем другая история. Однако, когда вы закрываете объединенное соединение, вы вместо этого возвращаете его в пул: под обложками SNAC выдает sp_reset_connection и помещает соединение обратно в пул. Как правило, это очень быстрая операция (если не блокировать пинки), но она должна принимать небольшое, но ненулевое время. Повторное использование того же соединения без закрытия и открытия для каждой итерации позволяет избежать этого небольшого запаздывания. Однако, если бы вы сравнили использование same объединенных и не объединенных соединений, это имело бы для меня больше смысла. Вы пробовали это?

Here's an interesting post on sp_reset_connection

4
добавлено
+1 Ваш ответ и ссылка полезны. Что касается вашего вопроса, я, конечно, мог бы «сравнить то же использование объединенных и не объединенных соединений», но почему это интересно? Обычно я использую объединение пулов. Существуют ли какие-либо сценарии, когда я должен отключить его?
добавлено автор A-K, источник
@StrayCatDBA существует множество обновлений надежности платформы .net. Какой из них вы использовали?
добавлено автор A-K, источник
Существует обновление надежности платформы .net, которое вызывает проверку, чтобы убедиться, что соединение все еще хорошо, прежде чем повторно использовать его. если соединение плохое, оно будет открыто открыто. Это необходимо для sql azure.
добавлено автор StrayCatDBA, источник
> Есть ли какие-либо сценарии, когда я должен отключить его? Может быть. С отказоустойчивой кластеризацией и зеркалированием базы данных вы можете заканчивать работу с неверными подключениями в вашем пуле после сбоя. Вместо того, чтобы полностью отключить пул, вы можете сбросить пул. Не знаю, отвечает ли он на ваш вопрос.
добавлено автор spaghettidba, источник
Это отличная информация! Спасибо, что поделился.
добавлено автор spaghettidba, источник

+1 к @spaghettidba - согласен, а также добавить комментарии .....

Мой подход в прошлом заключался в том, чтобы использовать одно и то же соединение несколько раз - за исключением того, что даже каждый раз, когда я всегда принимал (не измерял), чтобы подключиться к пулу соединений, чтобы получить соединение, стоимость some как сказал @spaghettidba.

Основным преимуществом производительности пула является сценарий, когда он не имеет смысла/не может повторно использовать один и тот же экземпляр подключения - в этом случае получение ранее использованного соединения из пула происходит намного быстрее, поскольку на самом деле оно не требуется уйти и фактически попытаться подключиться к серверу, он просто предполагает, что он есть и доступен - т.е. connection.Open() по моему опыту не является ошибкой для объединенного соединения, даже если сервер не работает - это будет просто ошибка при попытке выполнить что-либо против соединения.

1
добавлено
+1 yes, connection.Open() не вызывает никакой активности, которую я могу наблюдать в Profiler. Я буду видеть sp_reset_connection, когда я запускаю команду против моего повторно используемого соединения.
добавлено автор A-K, источник