Подтвердить что ты не робот

Выполнение нескольких команд SQL в одном раунде

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

Итак, я сохранил procs (или просто простые команды sql, такие как "select * from Users" ), и я хочу выполнить три из них. Однако, чтобы заполнить эту страницу, мне нужно совершить 3 круглых поездки.

Теперь я мог бы написать один сохраненный proc ( "getUsersTeamsAndPermissions" ) или выполнить одну команду SQL "select * from Users", exec getTeams, выбрать * из Permissions ".

Но мне было интересно, есть ли лучший способ указать, чтобы сделать 3 операции за один раунд. Преимущества включают в себя более легкое unit test и позволяя движку базы данных parrallelize запросов.

Я использую С# 3.5 и SQL Server 2008.

4b9b3361

Ответ 1

Единая команда с несколькими частями и параметры хранимой процедуры, которые вы упоминаете, являются двумя параметрами. Вы не можете делать их так, чтобы они "распараллеливались" на db. Тем не менее, оба этих варианта приводят к однократной поездке туда, поэтому вы там хорошо. Невозможно отправить их более эффективно. В sql-сервере 2005 года очень эффективная команда с несколькими параметрами очень эффективна.

Изменить: добавление информации о том, зачем вставлять один вызов.

Хотя вы не хотите слишком беспокоиться о сокращении вызовов, для этого могут быть законные причины.

  • Я когда-то был ограничен громоздким драйвером ODBC против мэйнфрейма, и на каждый вызов приходилось 1,2 секунды накладные расходы! Я серьезно. Были времена, когда я переполнял немного лишних звонков. Не красиво.
  • Вы также можете оказаться в ситуации, когда вам нужно сконфигурировать ваши SQL-запросы где-то, и вы не можете просто сделать 3 вызова: это должно быть одно. Это не должно быть так, плохой дизайн, но это так. Вы делаете то, что должны делать!
  • Иногда, конечно, очень удобно инкапсулировать несколько шагов в хранимой процедуре. Обычно это не для сохранения поездок в оба конца, но для более сложных транзакций, получения идентификатора для новых записей, ограничения для разрешений, обеспечения инкапсуляции, бла-бла-бла. (Но, пожалуйста, не начинайте использовать хранимые процедуры все время.)

Ответ 2

Что-то вроде this. Пример, вероятно, не очень хорош, так как он неправильно распоряжается объектами, но вы получаете эту идею. Здесь очищенная версия:

using (var connection = new SqlConnection(ConnectionString))
using (var command = connection.CreateCommand())
{
    connection.Open();
    command.CommandText = "select id from test1; select id from test2";
    using (var reader = command.ExecuteReader())
    {
        do
        {
            while (reader.Read())
            {
                Console.WriteLine(reader.GetInt32(0));
            }
            Console.WriteLine("--next command--");
        } while (reader.NextResult());

    }
}

Ответ 3

Создание одного раунда в три раза будет более эффективным. Вопрос в том, что это стоит того. Все инструменты и рамки ADO.Net и С# 3.5 противодействуют тому, что вы пытаетесь сделать. TableAdapters, Linq2SQL, EF, все это похоже на простую семантику one-call == one-resultset. Таким образом, вы можете потерять некоторую серьезную производительность, пытаясь победить Framework в подчинение.

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

Но если ваш запрос действительно является тем, что вы опубликовали (т.е. выберите всех пользователей, все команды и все разрешения), то у вас есть obviosuly гораздо больше рыбы, чтобы поджарить, прежде чем уменьшить круговые поездки... сначала уменьшите результаты.

Ответ 4

Мне эта эта ссылка может быть полезна.

Рассмотрите возможность использования, по крайней мере, одного и того же соединения; в соответствии с тем, что он говорит здесь, открытие соединения почти лидирует по производительности в Entity-Framework.

Ответ 5

Создайте временную таблицу? Вставьте все результаты в таблицу temp, а затем select * from @temp-table

как в,

@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2

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

Ответ 6

Во-первых, 3 поездки в оба конца не очень важны. Если бы вы говорили о 300 круглых поездках, тогда это было бы другим вопросом, но всего за три раунда я мог бы сделать это, чтобы определить, что это будет преждевременная оптимизация.

Тем не менее, способ, которым я это сделал, вероятно, состоял бы в том, чтобы выполнить 3 сохраненных procuedres, используя SQL:

exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2
exec dbo.p_myproc_2
exec dbo.p_myproc_3

Затем вы можете выполнять итерацию с помощью возвращаемых наборов результатов, как если бы вы выполняли сразу несколько наборов строк.