#sql #sql-server-2005 #indexing
#sql #sql-server-2005 #индексирование
Вопрос:
После масштабной реорганизации базы данных мне нужно удалить из нее все индексы и установить новые индексы.
Я нашел хороший scrpipt для получения всех индексов и удаления, но у меня проблема — я не могу удалить индексы, созданные ограничением ПЕРВИЧНОГО КЛЮЧА. (возможно, есть и другие типы индексов, которые я не могу удалить).
Мой вопрос: как изменить приведенный ниже код, чтобы удалить все индексы, кроме индексов, созданных для первичных ключей или других, которые я не могу удалить вручную.
DECLARE @indexName VARCHAR(128)
DECLARE @tableName VARCHAR(128)
DECLARE [indexes] CURSOR FOR
SELECT [sysindexes].[name] AS [Index], [sysobjects].[name] AS [Table]
FROM [sysindexes]
INNER JOIN [sysobjects] ON [sysindexes].[id] = [sysobjects].[id]
WHERE [sysindexes].[name] IS NOT NULL AND [sysobjects].[type] = 'U'
OPEN [indexes]
FETCH NEXT FROM [indexes] INTO @indexName, @tableName
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC ('DROP INDEX [' @indexName '] ON [' @tableName ']')
FETCH NEXT FROM [indexes] INTO @indexName, @tableName
END
CLOSE [indexes]
DEALLOCATE [indexes]
Ответ №1:
Вы можете попробовать использовать sys.indexes
представление каталога вместо устаревшего sysindexes
.
В этом представлении каталога есть вызов столбца is_primary_key
, поэтому вы должны быть в состоянии найти все индексы, отличные от первичного ключа, следующим образом:
SELECT *
FROM sys.indexes
WHERE is_primary_key = 0
Вы можете легко создать свои инструкции DROP INDEX из этого:
SELECT 'DROP INDEX ' name ' ON ' object_name(object_id)
FROM sys.indexes
WHERE is_primary_key = 0
AND object_ID > 255 -- exclude system-level tables with object_id <= 255
AND name IS NOT NULL -- exclude heaps with a NULL index name
Просто скопируйте и вставьте выходные данные этого оператора и запустите его — и все должно быть готово.
Комментарии:
1. Использовать эту таблицу — хороший совет, спасибо, но запускать сгенерированный ею код рискованно — он удалит также индексы из системных таблиц и вернет null для типа индекса КУЧИ — код из моего примера возвращает только индексы для пользовательских таблиц
2. ЕСЛИ вы добавите
AND object_ID > 255 AND name IS NOT NULL
к этому оператору, вы получите тот же результат; все таблицы «системного уровня» (id < 255) исключаются, как и кучи (где имя индекса равно NULL)3. хорошо, спасибо — это намного лучше. Теперь есть мои индексы и несколько индексов, таких как: «queue_clustered_index» — вы знаете, что это такое?
4. @Korn — Марек К. извините, я не знаю вашей базы данных — я не могу сказать вам, что это такое ….. в инструкции DROP INDEX должно быть указано, в какой таблице определен этот индекс — проверьте эту таблицу….
Ответ №2:
Основываясь на ответе Marc_s, я нашел правильную версию скрипта:
SELECT 'DROP INDEX ' name ' ON ' object_name(object_id)
FROM sys.indexes
WHERE is_primary_key = 0 AND is_unique_constraint = 0
AND OBJECTPROPERTY(object_id, 'IsMSShipped') = 0 -- exclude system-level tables
AND name IS NOT NULL
Проверки того, что object_Id больше 255, недостаточно:
— нам пришлось использовать OBJECTPROPERTY(object_id, ‘IsMSShipped’) = 0, потому что некоторые системные таблицы, такие как queue_messages, имеют очень высокий идентификатор
— также мы должны проверить, создан ли индекс с помощью уникального ограничения: is_unique_constraint = 0
После этих улучшений будут удалены все индексы, созданные пользователем.