Дилемма производительности T-SQL при циклическом просмотре большой таблицы (подробности внутри)

#performance #tsql

#Производительность #tsql

Вопрос:

Допустим, у меня есть Big и Bigger таблица. Мне нужно циклически просматривать Big таблицу, которая проиндексирована, но не последовательна (поскольку это фильтр последовательно индексируемой Bigger таблицы).

Для этого примера предположим, что мне нужно было перебрать около 20000 строк.

Должен ли я выполнить 20000 из них

 set @currentID = (select min(ID) from myData where ID > @currentID)
  

или

Создаем (большую) временную последовательно индексируемую таблицу (копию Big таблицы) и выполняем 20000 из

 @Row = @Row   1
  

?

Я полагаю, что выполнение 20000 фильтров Bigger таблицы только для извлечения следующего идентификатора является тяжелым, но поэтому должно быть заполнение большой ( Big размера) временной таблицы только для добавления фиктивного столбца идентификатора.

Есть ли решение где-то в другом месте? Например, если бы я мог циклически просматривать результаты оператора select (фильтр Bigger таблицы, из которой исходит «таблица» (фактически результирующий набор) Big ) без необходимости создания временных таблиц, это было бы идеально, но, похоже, я не могу добавить что-то вроде фиктивного столбца IDENTITY (1,1) к результатам.

Спасибо!

Комментарии:

1. Как myData таблица вписывается в это? И мне нужно будет посмотреть примерные данные, потому что я понятия не имею, о чем вы спрашиваете.

2. Вам нужно рассказать нам больше о том, чего вы пытаетесь достичь и в какой версии (предположительно) SQL Server. Очень вероятно, что вы можете выполнить это в одном запросе без необходимости в цикле.

3. Требуется обработать всего 20 тысяч элементов, и у вас проблемы с производительностью?

4. Ваши цифры и ваши субъективные выводы предполагают, что вам, вероятно, нужно привлечь кого-то, кто разбирается в базах данных. Это выходит за рамки одного-двух абзацев в Stackoverflow. «Сквозной цикл» — концептуальный способ для начинающих.

Ответ №1:

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

Ответ №2:

Вам необходимо предоставить больше информации о том, каков ваш конечный результат, только в очень редких случаях требуется выполнять построчную обработку (и почти всегда это наихудший возможный выбор с точки зрения производительности). Эта статья поможет вам начать с того, как выполнять многие задачи на основе наборов: http://wiki.lessthandot.com/index.php/Cursors_and_How_to_Avoid_Them

Если вам просто нужна временная таблица с идентификатором, вот два метода:

 create table #temp ( test varchar (10) , id int identity)
insert #temp (test)
select  test from mytable

select  test, identity(int) as id into #temp from mytable
  

Ответ №3:

Я думаю, что объединение лучше послужит вашим целям.

 SELECT BIG.*, BIGGER.*, -- Add additional calcs here involving BIG and BIGGER.
FROM TableBig BIG (NOLOCK)
JOIN TableBigger BIGGER (NOLOCK)
  ON BIG.ID = BIGGER.ID
  

Это ограничит набор, с которым вы работаете, до. Но опять же, это зависит от специфики вашего решения.

Помните также, что вы также можете выполнять массовые вставки и массовые обновления таким образом.