почему процесс SQLCLR будет работать медленнее, чем тот же код на стороне клиента

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

Первый шаг в упражнении заключался в том, чтобы просто просмотреть таблицу, что и делает приведенный ниже код. Проблема в том, что этот код запускается за 5:45 секунд, однако тот же код запускается как консольное приложение (конечно, с изменением строки подключения) запускается примерно за 44 секунды.

    using (SqlConnection sqlConnection = new SqlConnection("context connection=true"))
    {
        sqlConnection.Open();
        string sqlText = string.Format("select * from {0}", source_table.Value);
        int count = 0;
        using (SqlCommand sqlCommand = new SqlCommand(sqlText, sqlConnection))
        {
            SqlDataReader reader = sqlCommand.ExecuteReader();
            while (reader.Read())
                count++;
            SqlDataRecord record = new SqlDataRecord(new SqlMetaData("rowcount", SqlDbType.Int));
            SqlContext.Pipe.SendResultsStart(record);
            record.SetInt32(0, count);
            SqlContext.Pipe.SendResultsRow(record);
            SqlContext.Pipe.SendResultsEnd();
        }
    }

Однако тот же код (конечно, другая строка подключения) выполняется в консольном приложении примерно за 44 секунды (что ближе к тому, что я ожидал на стороне клиента).

Чего мне не хватает на стороне SP, из-за чего он работает так медленно.

Обратите внимание: я полностью понимаю, что если мне нужно подсчитать количество строк, я должен использовать агрегацию count(*) --- это не цель этого упражнения.


person Ralph Shillington    schedule 19.05.2009    source источник


Ответы (2)


Тип кода, который вы пишете, очень восприимчив к SQL-инъекциям. Вместо обработки средства чтения, как вы, вы можете просто использовать свойство RecordsAffected, чтобы найти количество строк в средстве чтения.

РЕДАКТИРОВАТЬ:

После некоторых исследований разница, которую вы видите, заключается в конструктивной разнице между контекстным соединением и обычным соединением. Питер Дебетта написал об этом в своем блоге:

«Контекстное соединение написано таким образом, что оно извлекает только строку за раз, поэтому для каждой из 20 миллионов нечетных строк код запрашивал каждую строку отдельно. Однако, используя неконтекстное соединение, он запрашивает 8 КБ. строк за раз».

http://sqlblog.com/blogs/peter_debetta/archive/2006/07/21/context-connection-is-slow.aspx

person Jonathan Kehayias    schedule 19.05.2009
comment
Вопрос был не о взломах SQL-инъекций и не о подсчете строк, а о производительности SqlDataReader, поэтому я включил исходный отказ от ответственности. - person Ralph Shillington; 19.05.2009
comment
После некоторых исследований разница, которую вы видите, заключается в конструктивной разнице между контекстным соединением и обычным соединением. Питер Дебетта написал об этом в блоге и пишет: Контекстное соединение написано таким образом, что оно извлекает только строку за раз, поэтому для каждой из 20 миллионов нечетных строк код запрашивал каждую строку отдельно. Однако, используя неконтекстное соединение, он одновременно запрашивает 8 КБ строк. sqlblog.com/blogs/peter_debetta/ архив/21.07.2006/ - person Jonathan Kehayias; 28.05.2009

Ну, казалось бы, ответ все-таки в строке подключения.

context connection=true

против

server=(local); database=foo; integrated security=true

По какой-то странной причине при использовании «внешнего» подключения SP работает почти так же быстро, как консольное приложение (все же не так быстро, заметьте! — 55 секунд).

Конечно, теперь сборка должна быть развернута как внешняя, а не как безопасная --- и это приводит к еще большему разочарованию.

person Ralph Shillington    schedule 19.05.2009