Индексирование одноразовой временной таблицы

Коллега работает в компании, использующей Microsoft SQL Server. Их команда создает хранимые процедуры, которые выполняются ежедневно для создания извлечений данных. Базовые таблицы огромны (некоторые содержат миллиарды строк), поэтому большинство хранимых процедур спроектированы таким образом, что сначала они извлекают только соответствующие строки этих огромных таблиц во временные таблицы, а затем временные таблицы соединяются друг с другом и с другими меньшими таблицами. таблицы для создания окончательной выписки. Что-то похожее на это:

SELECT COL1, COL2, COL3
INTO #TABLE1
FROM HUGETABLE1
WHERE COL4 IN ('foo', 'bar');

SELECT COL1, COL102, COL103
INTO #TABLE2
FROM HUGETABLE2
WHERE COL14 = 'blah';

SELECT COL1, COL103, COL306
FROM #TABLE1 AS T1
JOIN #TABLE2 AS T2
ON T1.COL1 = T2.COL1
LEFT JOIN SMALLTABLE AS ST
ON T1.COL3 = ST.COL3
ORDER BY T1.COL1;

Как правило, временные таблицы не изменяются после их создания (поэтому никаких последующих операций ALTER, UPDATE или INSERT). Для целей этого обсуждения предположим, что временные таблицы используются позже только один раз (поэтому на них будет полагаться только один запрос SELECT).

Вот вопрос: стоит ли индексировать эти временные таблицы после их создания и до того, как они будут использованы в последующем запросе?

Мой коллега считает, что создание индекса ускорит операции соединения и сортировки. Я считаю, однако, что общее время будет больше, потому что создание индекса требует времени. Другими словами, я предполагаю, что за исключением пограничных случаев (таких как временная таблица, которая сама по себе очень велика, или окончательный запрос SELECT очень сложен), SQL Server будет использовать статистику, которую он имеет по временным таблицам, для оптимизации окончательного запроса. и при этом он будет эффективно индексировать временные таблицы по своему усмотрению.

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

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


person Merik    schedule 28.06.2018    source источник


Ответы (2)


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

Вот вопрос: стоит ли индексировать эти временные таблицы после их создания и до того, как они будут использованы в последующем запросе?

Создайте индекс после загрузки данных во временную таблицу. Это устранит фрагментацию и будет создана статистика.

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

В приведенном ниже примере запрашивается сравнение до и после создания индекса во временной таблице:

/* Create index after data load into temp table -- stats is created */
CREATE TABLE #temp ( [text] varchar(50), [num] int);
INSERT INTO #temp([text], [num]) VALUES ('aaa', 1), ('bbb', 2) , ('ccc',3);
CREATE UNIQUE CLUSTERED INDEX [IX_num] ON #temp (num);
DBCC SHOW_STATISTICS ('tempdb..#temp', 'IX_num');

/* Create index before data load into temp table -- stats is not created */
CREATE TABLE #temp_nostats ( [text] varchar(50), [num] int);
CREATE UNIQUE CLUSTERED INDEX [IX_num] ON #temp_nostats (num);
INSERT INTO #temp_nostats([text], [num]) VALUES ('aaa', 1), ('bbb', 2) , ('ccc',3);
DBCC SHOW_STATISTICS ('tempdb..#temp_nostats', 'IX_num');

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

person Community    schedule 28.06.2018
comment
Спасибо, dco, но вы ответили на другой вопрос: следует ли создавать индекс до или после загрузки данных. Здесь вопрос в том, следует ли вообще создавать индекс. Другими словами, если мы не создадим индекс, не будет ли SQL Server сначала собирать некоторую статистику в качестве первого шага выполнения окончательного запроса SELECT? - person Merik; 29.06.2018
comment
@Merik ЭТО ЗАВИСИТ. Вам нужно проверить, поможет вам индекс или нет. если у вас нет индекса в вашей таблице, SQL Server просканирует всю таблицу. Оптимизатор использует статистику для расчета оценочной кардинальной стоимости вашей таблицы или индекса. - person ; 01.07.2018
comment
Но если я создам индекс, SQL Server будет сканировать всю таблицу при создании индекса, не так ли? Это означает, что сканирования таблицы нельзя избежать так или иначе. - person Merik; 02.07.2018
comment
Можете ли вы предоставить несколько ссылок в поддержку этого? Насколько я понимаю индексирование, невозможно создать индекс без однократного сканирования всех данных. - person Merik; 04.07.2018
comment
@Merik В прошлый раз я упустил из виду план выполнения. он сканирует таблицу, когда данные существуют. Ваш пробег может варьироваться, если вы хотите создать индекс до или после создания временной таблицы. В большинстве случаев я бы создавал индекс последним для генерации статистики (это помогает оптимизатору генерировать оптимальный план). Как уже упоминалось, вам нужно проверить, поможет ли это вам создать индекс или нет. - person ; 04.07.2018

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

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

person STLDev    schedule 28.06.2018