Pull to refresh

Comments 35

А исходная проблема-то разрешилась? Т.е. обновление статистики не помогало, а теперь всё летает?

Обновление статистики помогало только если день - два переиндексация не проходила. Если дольше то начинались тормоза. Сейчас (уже 3 месяца) переиндексация проходит каждую ночь и тормозов больше не наблюдается. Так что да, помогло решить исходную проблему.

Обновление статистики так же каждую ночь делали?

Да, каждую ночь. Но из-за фрагментация таблицы, самых больших таблиц уже не хватало железа что бы переварить запросы (типо всяких select'ов от начало времен). Был еще вариант заставить программистов 1с переделать их обработки, но они не захотели)

хотел бы вас попросить сопровождение, на двух бд прошло успешно
на одной словил ошибку

Executing query "SET QUOTED_IDENTIFIER ON; if DB_ID('profiler') ...".: 100% complete End Progress Error: 2024-12-07 08:57:34.52 Code: 0xC002F210 Source: Execute T-SQL Statement Task 1 Execute SQL Task Description: Executing the query "DECLARE @FramentationReportTable_1 VARCHAR(255) ..." failed with the following error: "Incorrect syntax near 'bad_indexes_1'.".

В базе профайлер таблицы с именами такого вида Fragmentation_GoldenHome_Treasure_NEW_2012дата ?

Вот этот запрос выдает результат или ошибку?

DECLARE @FramentationReportTable_1 VARCHAR(255)
SET @FramentationReportTable_1 = (SELECT top 1 table_name FROM Profiler.INFORMATION_SCHEMA.TABLES WHERE table_Name LIKE 'Fragmentation_GoldenHome_Treasure_NEW_2012'+REPLACE(convert(varchar, getdate(), 102), '.', '_') + '%')
print @FramentationReportTable_1

exec ('

select
frag.db_name,
frag.schema_name,
frag.table_name,
frag.index_name,
frag.partition_num,
case
when frag.record_size16 <= 403 then 95 when frag.record_size16 <= 806 then 90
when frag.record_size*16 <= 1209 then 85
else 80
end as suggested_fillfactor

from Profiler.dbo.'+ @FramentationReportTable_1 +' frag
where frag.page_count > 24 and frag.fragmentation >= 5 and frag.num = 1 and frag.index_type <>''HEAP''
order by frag.fragmentation desc')

Пока как предположение, без полного запроса. Что дата в таблице в базе profiler идет с датой от вчера. и по этому курсор не смог задаться (так как ищет от сегодня данные). Если это так то запрос должен выдать ошибку, и получить данные если будет SET @FramentationReportTable_1 = (SELECT top 1 table_name FROM Profiler.INFORMATION_SCHEMA.TABLES WHERE table_Name LIKE 'Fragmentation_GoldenHome_Treasure_NEW_2012'+REPLACE(convert(varchar, getdate()-1, 102), '.', '_') + '%')

Fragmentation_GoldenHome_Treasure_NEW_2012_2024_12_07_1

Msg 208, Level 16, State 1, Line 3
Invalid object name 'Profiler.dbo.frag'.

Ой я тогда в запросе, который кинул _ забыл после имени БД 'Fragmentation_GoldenHome_Treasure_NEW_2012_' нужно

база проблемная
Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) Aug 22 2017 17:04:49 Copyright (C) 2017 Microsoft Corporation Standard Edition (64-bit) on Windows Server 2016 Standard 10.0 (Build 14393: ) (Hypervisor)

обе где успешно
Microsoft SQL Server 2022 (RTM-CU11) (KB5032679) - 16.0.4105.2 (X64) Nov 14 2023 18:33:19 Copyright (C) 2022 Microsoft Corporation Standard Edition (64-bit) on Windows Server 2022 Standard 10.0 (Build 20348: ) (Hypervisor)

все три разных хоста

Fragmentation_GoldenHome_Treasure_NEW_2012_2024_12_07_1
Msg 207, Level 16, State 1, Line 3
Invalid column name 'record_size16'.
Msg 207, Level 16, State 1, Line 3
Invalid column name 'record_size16'.

Completion time: 2024-12-07T10:29:30.5579878+03:00

Кажется в запросе где знаки потерялись при копирование у меня

DECLARE @FramentationReportTable_1 VARCHAR(255)
SET @FramentationReportTable_1 = (SELECT top 1 table_name FROM Profiler.INFORMATION_SCHEMA.TABLES WHERE table_Name LIKE 'Fragmentation_GoldenHome_Treasure_NEW_2012_'+REPLACE(convert(varchar, getdate(), 102), '.', '_') + '%')
print @FramentationReportTable_1

exec ('

select
frag.db_name,
frag.schema_name,
frag.table_name,
frag.index_name,
frag.partition_num,
case
when frag.record_size*16 <= 403 then 95

when frag.record_size*16 <= 806 then 90
when frag.record_size*16 <= 1209 then 85
else 80
end as suggested_fillfactor

from Profiler.dbo.'+ @FramentationReportTable_1 +' frag
where frag.page_count > 24 and frag.fragmentation >= 5 and frag.num = 1 and frag.index_type <>''HEAP''
order by frag.fragmentation desc')

успешно выполнено есть 31 строка
куда мне дальше

А пришли, весь запрос который у тебя получился в скрипте, который не работает (насколько я понимаю это номер 2 должен быть что у меня в статье)

DECLARE @FramentationReportTable_1 VARCHAR(255)
SET @FramentationReportTable_1 = (SELECT top 1 table_name FROM Profiler.INFORMATION_SCHEMA.TABLES WHERE table_Name LIKE 'Fragmentation_GoldenHome_Treasure_NEW_2012_'+REPLACE(convert(varchar, getdate(), 102), '.', '_') + '%')
print @FramentationReportTable_1

exec ('
DECLARE bad_indexes_1 CURSOR FOR

select
frag.db_name,
frag.schema_name,
frag.table_name,
frag.index_name,
frag.partition_num,
case
when frag.record_size16 <= 403 then 95 when frag.record_size16 <= 806 then 90
when frag.record_size*16 <= 1209 then 85
else 80
end as suggested_fillfactor

from Profiler.dbo.'+ @FramentationReportTable_1 +' frag
where frag.page_count > 24 and frag.fragmentation >= 5 and frag.num = 1 and frag.index_type <>''HEAP''
order by ROUND ([fragmentation],0 ) desc, [rows_count] desc')

-- Open the cursor.
OPEN bad_indexes_1

DECLARE @db_name nvarchar(130);
DECLARE @schema_name nvarchar(130);
DECLARE @table_name nvarchar(130);
DECLARE @index_name nvarchar(130);
DECLARE @fragmentation bigint;
DECLARE @suggested_fillfactor int;
DECLARE @partition_num bigint;
DECLARE @partitionOption nvarchar(130);
DECLARE @fillfactorOption nvarchar(130);
DECLARE @object_name nvarchar(1000);
DECLARE @command nvarchar(1000);
DECLARE @time nvarchar(130)

WHILE (1=1)
BEGIN
FETCH NEXT
FROM bad_indexes_1
INTO @db_name, @schema_name, @table_name, @index_name, @partition_num, @suggested_fillfactor;

IF @FETCH_STATUSS < 0 BREAK

IF @partition_num > 1
begin
SET @partitionOption = N' PARTITION=' + CAST@partition_numm AS nvarchar(10));
set @fillfactorOption = N''
end
else
begin
SET @partitionOption = N''
set @fillfactorOption = N' FILLFACTOR=' + CAST@suggested_fillfactorr as nvarchar(10)) + N', '
end

SET @object_name = QUOTENAME@db_namee) + N'.' + QUOTENAME@schema_namee) + N'.' + QUOTENAME@table_namee)
BEGIN TRY

SET @command = N'ALTER INDEX ' + QUOTENAME(@index_name) + N' ON ' + @object_name + ' REBUILD ' + @partitionOption +' WITH(' + @fillfactorOption +  N'maxdop = 0, ONLINE = ON, SORT_IN_TEMPDB = ON, MAX_DURATION = 10 minutes, ABORT_AFTER_WAIT = BLOCKERS)'

set @time = CURRENT_TIMESTAMP;
print @time
RAISERROR@commandd, 0, 1)
EXEC@commandd)
set @time = CURRENT_TIMESTAMP;
RAISERROR(N'DONE', 0, 1)
END TRY
BEGIN CATCH
SET @command = N'ALTER INDEX ' + QUOTENAME@index_namee) + N' ON ' + @object_name + ' REBUILD ' + @partitionOption +' WITH(' + @fillfactorOption + N'maxdop = 0, SORT_IN_TEMPDB = ON)'
set @time = CURRENT_TIMESTAMP;
print @time
RAISERROR@commandd, 0, 1)
EXEC@commandd)
set @time = CURRENT_TIMESTAMP;
RAISERROR(N'DONE', 0, 1)
print @time
END CATCH
END

close bad_indexes_1
deal

Тоже смотрю у тебя часть запроса потерялась при копирование.

должно быть IF @@FETCH_STATUS < 0 BREAK

а у тебя IF @FETCH_STATUSS < 0 BREAK

Кстати можешь попробовать на сервере выполнить запрос (корректный) просто закоментив обе строки с переиндексацией вот эти SET @command = N'ALTER INDEX '  .... и тогда будет проще увидеть где ошибка

ща попробуем запрос проверить
и за коменнтить

Executed as user: NT Service\SQLSERVERAGENT. Microsoft (R) SQL Server Execute Package Utility Version 14.0.1000.169 for 64-bit Copyright (C) 2017 Microsoft. All rights reserved. Started: 12:32:42 PM Progress: 2024-12-07 12:32:43.29 Source: {3F75105D-FFED-468F-8903-4844FFB5DE7E} Executing query "DECLARE @Guid UNIQUEIDENTIFIER EXECUTE msdb..sp...".: 100% complete End Progress Progress: 2024-12-07 12:32:50.71 Source: Execute T-SQL Statement Task Executing query "SET QUOTED_IDENTIFIER ON; if DB_ID('profiler') ...".: 100% complete End Progress Error: 2024-12-07 12:32:50.76 Code: 0xC002F210 Source: Execute T-SQL Statement Task 2 Execute SQL Task Description: Executing the query "DECLARE @FramentationReportTable_2 VARCHAR(255) ..." failed with the following error: "Incorrect syntax near 'bad_indexes_2'.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly. End Error Error: 2024-12-07 12:32:50.76 Code: 0xC002F210 Source: Execute T-SQL Statement Task 1 Execute SQL Task Description: Executing the query "DECLARE @FramentationReportTable_1 VARCHAR(255) ..." failed with the following error: "Incorrect syntax near 'bad_indexes_1'.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly. End Error Warning: 2024-12-07 12:32:50.76 Code: 0x80019002 Source: Subplan_1 Description: SSIS Warning Code DTS_W_MAXIMUMERRORCOUNTREACHED. The Execution method succeeded, but the number of errors raised (2) reached the maximum allowed (1); resulting in failure. This occurs when the number of errors reaches the number specified in MaximumErrorCount. Change the MaximumErrorCount or fix the errors. End Warning DTExec: The package execution returned DTSER_FAILURE (1). Started: 12:32:42 PM Finished: 12:32:50 PM Elapsed: 8.078 seconds. The package execution failed. The step failed.

Это больше похоже на ошибку из лога. Я имел ввиду new quary весь 2ой или 3й шаг из статьи на сервере выполнить. закометив строку с переиндексации.

Так ошибка в логах и не исполняет
я за коментил в скрипте2 ща во втором тоже сделаю

или мне в отношение базы profile нужно исполнить запросы 2 и 3?

Msg 102, Level 15, State 1, Line 87
Incorrect syntax near 'bad_indexes_1'.

Msg 102, Level 15, State 1, Line 87
Incorrect syntax near 'bad_indexes_2'.

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

Line 87 это конец скрипта. далее deal
я см. в notepad++ с отображением символов

все точно упущено (((
close bad_indexes_1
deallocate bad_indexes_1

скрипт отработал. спасибо за сопровождение. копировал через Ctr+a , почему образалось в оба скрипта с двух разных вкладок не ясно.
мое почтение.

А зачем вам успевать в техокно?, у меня самая большая база в терабайт сейчас, работает 2 скрипта, один занимается индексированием, второй сбором статистики, всё выполняется online, в скриптах для снижения нагрузки реализован механизм проверки, не выполняется ли сейчас бэкап в базе... Работает уже пол года, полет отличный, пару таблиц есть в базе, которые нельзя инлексировать online, но практика показывает, что проблем не возникает из за этого.

Индексация выполняется только тех, которые действительно надо, то же самое со статистикой, а не всё подряд

А как ваш скрипт учитывает плотность страниц, о которой вы пишете в тексте? Ну, не считая того, что уменьшает её, уменьшая для всех таблиц fill factor?

А зачем мне учитывать плотность страниц при перестройке индекса в общем случае без точной специфики работы базы. Ведь априори, если уменьшая фрагментацию, мы увеличиваем плотность данных на страницах. Вопрос изначальный в статье о том, что переиндексация нужна. А оставлять fill factor 0 чревато тем, что при любой вставке будет проходить разбиение и фрагментация будет расти слишком быстро. Но при этом и не желательно делать слишком много пустого пространства, из за которого плотность будет меньше. а общее условие suggested_fillfactor позволяет найти компромисс от полного заполнения станиц и как следствие каждодневное повышение фрагментации и сохранить плотность на должном уровне.

Ведь априори, если уменьшая фрагментацию, мы увеличиваем плотность данных на страницах

Это ложное утверждение. C fill factor < 100 вы скорее её уменьшаете, но поскольку не отслеживаете - подтвердить или опровергнуть это не получится. Однако люди, которые запустят ваши скрипты, могут сильно удивиться, что индексы выросли, и памяти теперь нужно больше, чем до дефрагментации.

suggested_fillfactor позволяет найти компромисс от полного заполнения станиц и как следствие каждодневное повышение фрагментации и сохранить плотность на должном уровне

А кем он suggested? Зачем он безльтернативно suggested для всех таблиц с фрагментацией больше 5%? А если это историческая таблица с индексом по дате, в которой все изменения происходят в последнем месяце?

Не думаю что есть люди которые берут чужие скрипты и пихаюх их в прод без проверки. Так же после 2и3 скрипта я указал про моменты что есть - fillfactor, есть проверка по партиция (и переиндексация только фрагментированных партиций) и про условия. так же было указано что это общая light версия.

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

Предложенный мной и частью других статей (https://www.sqlservercentral.com/только там чаще про 80% говорят) но также везде сказано что нужно смотреть производительность.

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

Sign up to leave a comment.

Articles