На этом сайте рассказывается о том, как статистика для временной таблицы может быть устаревшей, т. е. может храниться для последнего запуска.
https://www.sql.kiwi/2012/08/temporary-tables-in-stored-procedures.html
Перейдите в раздел «Использование временной таблицы».
Я попытался повторить это с помощью кода ниже.
Первая проблема заключалась в том, что столбец «somecolumn» не был распознан. Ответ на этот вопрос, казалось, заключался в том, что фактические имена столбцов во временных таблицах кодируются, и ответ заключался в использовании «создать статистику».
Вторая проблема в том, что я не вижу тех же результатов. При первом вызове SP я получаю статистику, т.е.
но во второй раз я этого не делаю
Вот код. Таблица «Сотрудник» является локальной таблицей, чтобы запустить ее, просто замените ее какой-нибудь таблицей в вашей базе данных. Фактические данные не имеют значения, если в таблице есть несколько строк.
ALTER PROCEDURE dbo.TempTableTest
@INDEX INT, @ROWCOUNT INT
AS
BEGIN
CREATE TABLE #TEMP
(
SOMECOLUMN INT,
SOMECOLUMN2 uniqueidentifier,
SOMECOLUMN3 uniqueidentifier,
)
CREATE STATISTICS MYSTATS ON #TEMP (SOMECOLUMN)
insert into #temp
select top (@rowcount) 1,newid(), newid() from employee empa
join employee empb on 1=1
--UPDATE STATISTICS #Temp;
select count(*) FROM #TEMP
select * FROM #TEMP WHERE SOMECOLUMN=@INDEX
-- this must follow the select on the #temp table
DBCC SHOW_STATISTICS (N'tempdb..#Temp', 'MYSTATS')
WITH STAT_HEADER, HISTOGRAM;
DROP TABLE #temp;
END
GO
Запустите это с помощью
-- EXEC TempTableTest 2, 400
Первая проблема заключалась в том, что столбец «somecolumn» не был распознан.
Разве не был признан DBCC SHOW_STATISTICS?
Запуск вашего кода с закомментированным CREATE STATISTICS
(и использованием удобной локальной таблицы):
ALTER PROCEDURE dbo.TempTableTest
@INDEX INT, @ROWCOUNT INT
AS
BEGIN
CREATE TABLE #TEMP
(
SOMECOLUMN INT,
SOMECOLUMN2 uniqueidentifier,
SOMECOLUMN3 uniqueidentifier,
)
--CREATE STATISTICS MYSTATS ON #TEMP (SOMECOLUMN)
insert into #temp
select top (@rowcount) 1,newid(), newid() from dbo.Numbers AS N
join dbo.Numbers AS N2 ON 1 = 1
--UPDATE STATISTICS #Temp;
select count(*) FROM #TEMP
select * FROM #TEMP WHERE SOMECOLUMN=@INDEX
-- this must follow the select on the #temp table
DBCC SHOW_STATISTICS (N'tempdb..#Temp', 'SOMECOLUMN')
WITH STAT_HEADER, HISTOGRAM;
DROP TABLE #temp;
END
GO
EXECUTE dbo.TempTableTest
@INDEX = 2, -- int
@ROWCOUNT = 400 -- int
Я вижу стабильные результаты при первом и последующих запусках:
Ответ на этот вопрос, казалось, заключался в том, что фактические имена столбцов во временных таблицах кодируются, и ответ заключался в использовании «создать статистику».
Я думаю, что под «закодированным» вы имеете в виду обычное соглашение об именах для автоматически создаваемой статистики, то есть префикс, порядковый номер столбца, шестнадцатеричное представление идентификатора объекта.
Например, в _WA_Sys_00000002_5F141958
_WA_Sys_
— это префикс, 2
— порядковый номер столбца, а 5F141958
— это идентификатор объекта временной таблицы в шестнадцатеричном формате. Идентификатор объекта изменится, если временная таблица не кэшируется.
Использовать CREATE STATISTICS
— не лучшая идея. Как я писал в разделе Объяснение временного кэширования таблиц:
Статистика, созданная с использованием явного оператора
CREATE STATISTICS
, не связана с кэшированным временным объектом, посколькуCREATE STATISTICS
считается DDL и вообще предотвращает кэширование.
Другими словами, явное создание статистики предотвращает поведение, которое вы надеетесь наблюдать.
Вторая проблема в том, что я не вижу тех же результатов. При первом вызове SP я получаю статистику.
См. выше.
Это умеренно сложная тема. Большинство людей считают, что им нужно прочитать обе статьи несколько раз, чтобы действительно понять все нюансы. Я постарался охватить в статьях как можно больше вопросов и крайних случаев. У меня просто нет времени отвечать каждому индивидуально и объяснять все детали. Тем не менее, я надеюсь, что вышесказанное вам поможет.