ОРИГИНАЛ ПРОБЛЕМАTempdb Полное При запросе Distinct Count всех таблиц
Я создал специальный скрипт для извлечения данных из удаленного сервера SQL в нашу локальную копию в нашем офисе. У меня были некоторые проблемы со сценарием, где в выбранных таблицах были вставлены некоторые данные дважды, что создает дубликаты. Я знаю, что для всех таблиц во всех базах данных не должно быть дубликатов.
Эта проблема сделала меня параноидальным, что другие таблицы могут иметь эту проблему исторически, и поэтому я хотел бы проверить это.
РЕШЕНИЕ
Я создал SQL скрипт для вставки количества и отчетливого количества всех столбцов в таблицу для всех баз данных на нашем сервере (за исключением 4 системных баз данных):
DECLARE @TableFullName AS NVARCHAR(MAX)
DECLARE @SQLQuery AS NVARCHAR(MAX)
DECLARE @TableHasDuplicates AS BIT
DECLARE @TempTableRowCount AS INT
DECLARE @ResultsTable TABLE ([CompleteTableName] NVARCHAR(200), [CountAll] INT, [CountDistinct] INT)
DECLARE @CountAll INT
DECLARE @CountDistinct INT
SET NOCOUNT ON
DECLARE @AllTables TABLE ([CompleteTableName] NVARCHAR(200))
INSERT INTO @AllTables ([CompleteTableName])
EXEC sp_msforeachdb 'SELECT ''['' + [TABLE_CATALOG] + ''].['' + [TABLE_SCHEMA] + ''].['' + [TABLE_NAME] + '']'' FROM [?].INFORMATION_SCHEMA.TABLES'
SET NOCOUNT OFF;
DECLARE [table_cursor] CURSOR FOR
(SELECT *
FROM @AllTables
WHERE [CompleteTableName] NOT LIKE '%master%' AND [CompleteTableName] NOT LIKE '%msdb%' AND [CompleteTableName] NOT LIKE '%tempdb%' AND [CompleteTableName] NOT LIKE '%model%');
OPEN [table_cursor]
PRINT N'There were ' + CAST(@CountAll AS NVARCHAR(10)) + ' tables with potential duplicate data'
FETCH NEXT FROM [table_cursor]
INTO @TableFullName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQLQuery = 'SELECT @CntAll = COUNT(*) FROM ' + @TableFullName + ' SELECT @CntDistinct = COUNT(*) FROM (SELECT DISTINCT * FROM ' + @TableFullName + ') AS [sq] IF @CntAll > @CntDistinct SELECT @BitResult=1 ELSE SELECT @BitResult=0';
EXEC sp_executesql @SQLQuery, N'@BitResult BIT OUTPUT, @CntAll INT OUTPUT, @CntDistinct INT OUTPUT', @BitResult = @TableHasDuplicates OUTPUT, @CntAll = @CountAll OUTPUT, @CntDistinct = @CountDistinct OUTPUT;
IF @TableHasDuplicates = 1
BEGIN
INSERT INTO @ResultsTable ([CompleteTableName], [CountAll], [CountDistinct])
SELECT @TableFullName, @CountAll, @CountDistinct
END;
FETCH NEXT FROM [table_cursor]
INTO @TableFullName
END
CLOSE [table_cursor];
DEALLOCATE [table_cursor];
SELECT *
FROM @ResultsTable
Обзор того, как он работает, является переменная таблицы @AllTables использует sp_msforeachdb с INFORMATION_SCHEMA.TABLES для отображения всех таблиц во всех базах данных (есть 16537 таблиц). Курсор таблицы используется для хранения всех несистемных записей, а затем я использую динамический SQL для вычисления счетчика и отдельного счета, который хранится в другой переменной таблицы @ResultsTable.
ПРОБЛЕМА С помощью этого решения
Когда я запускаю этот запрос, он будет работать действует около 3 минут, затем выдаст сообщение об ошибке сказав, что Tempdb ОСНОВНОЙ файловая группа полна:
Я мой собственный DBA, и я использовал Brent Ozar's guide для создания моего экземпляра SQL-сервера, и мой Tempdb устанавливается с 8 х 3GB/NDF МДФ файлов (сервер имеет 8 ядер):
Эти файлы имеют доступ к 23997 МБ в свойствах «Общие».
МОИ ВОПРОСЫ
- Если я около 24 Гб свободного пространства TempDb, почему это относительно простой запрос кончаются TempDb пространства?
- Есть ли лучший/более эффективный способ получения счета и отличного подсчета всех таблиц во всех базах данных?
Сколько данных обрабатывается? Если вы отличаетесь данными, имеющими много разных значений, то все эти значения оказываются во временной рабочей таблице. Обходные пути для этого нетривиальны. Вам нужно будет обработать таблицу в кусках. – usr
Спасибо, что ответили usr. Вы имеете в виду подзапрос: SELECT DISTINCT * FROM '+ @TableFullName? Это помещено в tempdb? Очевидно, он обрабатывает тысячи таблиц, поэтому, если он кэширует все эти таблицы (я бы подумал, что кеш будет очищен каждой итерацией цикла?), Тогда это будут сотни ГБ данных. – Quarcheek
Возможно, это так. – usr