Автономное приложение: поддерживайте работоспособность/отзывчивость базы данных с течением времени

У меня есть приложение WinForms С#, использующее базу данных MS SQL Server Express. Приложение развернуто на компьютерах наших клиентов, и они не имеют компьютерных знаний.

Приложение регулярно обновляет базу данных, и я вижу большую фрагментацию индексных файлов. Как поддерживать работоспособность/отзывчивость базы данных с течением времени?

Я думал о программировании хранимой процедуры, которая реорганизует каждый индекс, но мне не хватает навыков t-sql; может кто-нибудь вести меня в правильном направлении?

Бас


person Bas Jansen    schedule 27.10.2008    source источник


Ответы (4)


Используйте параметр DBCC REINDEX, если вы можете позволить себе ненадолго перевести таблицу в автономный режим, или DBCC INDEXDEFRAG. Однако опция IndexDefrag устарела. Вы также можете использовать оператор ALTER INDEX в SQL 2005/2008.

person baldy    schedule 27.10.2008

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

Нравится обновление статистики, проверка страниц на наличие ошибок, дефрагментация, переиндексация, сжатие?, .....

Как хранимая процедура «Сделать мою БД здоровой».

у кого есть такой скрипт?

person Community    schedule 27.10.2008

Также убедитесь, что ФАЙЛ вашей базы данных менее подвержен фрагментации. Это, по общему признанию, очень сложно сделать, поскольку вы не знаете, какова структура дисков ваших клиентов, но я предлагаю начать с файла .MDB с достаточно большим начальным размером, чтобы предотвратить онлайн-восстановления, которые отнимают время и ресурсы, и часто приводят к фрагментации на уровне файлов.

Дизайн вашего индекса также влияет на то, насколько фрагментированы ваши индексы. Вы должны убедиться, что индексы, которые вы вставляете во множество, имеют соответствующий низкий FILLFACTOR для предотвращения разделения страницы. Также избавьтесь от любых индексов, которые не используются.

Для дефрагментации индексов используйте команду DBCC DBREINDEX.

person Dave Markle    schedule 27.10.2008

Сейчас я использую 2 sql-скрипта.

SELECT 
    st.object_id AS objectid,
    st.index_id AS indexid,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS frag,
    o.name,
    i.name
FROM 
    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') st
join
    sys.objects o on o.object_id = st.object_id
join 
    sys.indexes i on st.object_id = i.object_id and i.index_id=st.index_id

Я запускаю это при запуске своей программы и проверяю, имеет ли avg_fragmentation_in_percent значение avg_fragmentation_in_percent больше 70. Если это так, я запускаю следующий скрипт.

SET NOCOUNT ON;
DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname nvarchar(130); 
DECLARE @objectname nvarchar(130); 
DECLARE @indexname nvarchar(130); 
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @command nvarchar(4000); 
-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 
-- and convert object and index IDs to names.

if ( object_id( 'tempdb..#work_to_do' ) is not null )
  DROP TABLE #work_to_do;

-- Alleen indexen die meer dan x% gefragemteerd zijn
SELECT
    object_id AS objectid,
    index_id AS indexid,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS frag
INTO #work_to_do
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 5.0 AND index_id > 0;

-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
WHILE (1=1)
    BEGIN;
        FETCH NEXT
           FROM partitions
           INTO @objectid, @indexid, @partitionnum, @frag;
        IF @@FETCH_STATUS < 0 BREAK;
        SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
        FROM sys.objects AS o
        JOIN sys.schemas as s ON s.schema_id = o.schema_id
        WHERE o.object_id = @objectid;
        SELECT @indexname = QUOTENAME(name)
        FROM sys.indexes
        WHERE  object_id = @objectid AND index_id = @indexid;
        SELECT @partitioncount = count (*)
        FROM sys.partitions
        WHERE object_id = @objectid AND index_id = @indexid;

        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD WITH (FILLFACTOR = 90)';
        IF @partitioncount > 1
            SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
        EXEC (@command);
        PRINT N'Executed: ' + @command;
    END;

-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;

-- Drop the temporary table.
DROP TABLE #work_to_do;

Этот скрипт дефрагментирует все таблицы с фрагментацией более 5%

person Bas Jansen    schedule 11.12.2009