#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
Это ограничит набор, с которым вы работаете, до. Но опять же, это зависит от специфики вашего решения.
Помните также, что вы также можете выполнять массовые вставки и массовые обновления таким образом.