|
v7: Статистика скульной базы | ☑ | ||
---|---|---|---|---|
0
dk
30.05.19
✎
12:30
|
Как проверить что не обновлена статистика в скуле?
Исходные 1с 77, MSQ SQL 2000 и 2008 Периодически начинает тупить база на ровном месте, обычно это означает что стата протухла Как можно проверить что пора обновить стату? |
|||
1
dk
30.05.19
✎
12:31
|
Пока есть идея перебрать критичные таблицы и их индексы и тупо запросы в пределах индексов накидать
может кто уже занимался подобные и есть наработки или в принципе подход неверный |
|||
2
zenon46
30.05.19
✎
12:46
|
(0) так вроде в свойствах БД есть параметр AutoCreat и AutoUpdate. Смысл это проверять если включено.
|
|||
3
dk
30.05.19
✎
12:59
|
база большая - полтерабайта
галка автообновления статы есть но это такое |
|||
4
dk
30.05.19
✎
13:01
|
полное обновление статы - больше суток, поэтому надо выкручиваться
|
|||
5
zenon46
30.05.19
✎
13:04
|
(3) не кислый размерчик.
|
|||
6
trad
30.05.19
✎
13:09
|
Я думаю тут дело такое: статистика она или актуальна или не актуальна в какой-то степени))
Чтобы оценить насколько текущая статистика не актуальна нужно посчитать новую и сравнить. Как бы нет такого места где бы это оценка уже лежала готовой. имхо все |
|||
7
dk
30.05.19
✎
13:28
|
(6) Думаю накидать простые запросы - только поля внутри индекса
и смотреть когда время запросов будет расти ------------------- --если индекс ID,OBJID,DATE,TIME,DOCID,ROW_ID select top 1 ROW_ID from _1sconst as c92_vv (nolock) where c92_vv.id = 92 and c92_vv.objid = ' 5RAD' and (c92_vv.date <= '20190506') order by c92_vv.date desc, c92_vv.time desc, c92_vv.docid desc, c92_vv.row_id desc ------------- ну и чутка играться параметрами - ссылками и датами |
|||
8
trad
30.05.19
✎
13:33
|
(7) ну в подобном запросе у оптимизатора не будет даже мысли не использовать индекс, к статистике (бабке) не ходи
|
|||
9
trad
30.05.19
✎
13:35
|
я бы сделал безусловный пересчет статистики с некоторой периодичностью по ночам. но раз все таблицы/индексы долго, то распределил бы пересчитываемые объекты равномерно по периоду
|
|||
10
dk
30.05.19
✎
13:36
|
а если select top 1 * ?
|
|||
11
trad
30.05.19
✎
13:37
|
Ну т.е. сегодня ночью считаем журн, завтра црдок, послезавтра один тяжелый ra, потом другой и т.д. в конце все остальное
Через месяц повторить |
|||
12
ДенисЧ
30.05.19
✎
13:38
|
А так http://www.sql.ru/forum/1116402/kak-opredelit-aktualnost-statistiki не пробовали?
|
|||
13
dk
30.05.19
✎
13:39
|
задача узнавать о проблеме раньше чем полетят письма "счастья" от пользователей
или например задания на какомто из серверов по обновлению статы перестали отрабатывать |
|||
14
ДенисЧ
30.05.19
✎
13:40
|
И ещё чуть про статистики
http://sql-ex.ru/blogs/optimization/statistics-in-sql-server.html |
|||
15
dk
30.05.19
✎
13:40
|
(12) 2000-е сервера есть
|
|||
16
serpentt
30.05.19
✎
13:46
|
(0) У нас запускается Job с процедурой
USE [master] GO /****** Object: StoredProcedure [dbo].[sp_defragment_frag_indexes] Script Date: 05/30/2019 13:44:49 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[sp_defragment_frag_indexes] @maxfrag DECIMAL, @whatif VARCHAR (6)='' AS --Запуск (ИмяБазы,ПроцентФрагментации) --USE t07serg --EXEC sp_defragment_frag_indexes 80.00; -- Объявляем необходимые переменные SET NOCOUNT ON DECLARE @tablename VARCHAR (128) DECLARE @execstr VARCHAR (255) DECLARE @objectid INT DECLARE @objectowner VARCHAR(255) DECLARE @indexid INT DECLARE @frag DECIMAL DECLARE @indexname CHAR(255) DECLARE @dbname sysname DECLARE @tableid INT DECLARE @tableidchar VARCHAR(255) -- На всякий случай проверяем,что база данных пользовательская SELECT @dbname = db_name(); IF @dbname IN ('master', 'msdb', 'model', 'tempdb') BEGIN PRINT 'Эта процедура не может быть запущена для системных БД'; RETURN END -- Начинаем проверку уровня фрагментации -- Вначале объявляем курсор DECLARE tables CURSOR FOR SELECT convert(varchar,so.id) FROM sysobjects so JOIN sysindexes si ON so.id = si.id WHERE so.type ='U' AND si.indid < 2 AND si.rows > 0; -- Затем создаем временную таблицу для хранения информации о фрагментации CREATE TABLE #fraglist (ObjectName CHAR (255), ObjectId INT, IndexName CHAR (255),IndexId INT, Lvl INT, CountPages INT, CountRows INT, MinRecSize INT, MaxRecSize INT, AvgRecSize INT, ForRecCount INT, Extents INT, ExtentSwitches INT, AvgFreeBytes INT, AvgPageDensity INT, ScanDensity DECIMAL, BestCount INT, ActualCount INT, LogicalFrag DECIMAL, ExtentFrag DECIMAL); -- Открываем курсор OPEN tables -- Для каждой таблицы в базе данных выполняем команду DBCC SHOWCONTIG FETCH NEXT FROM tables INTO @tableidchar WHILE @@FETCH_STATUS = 0 BEGIN -- Проходим по всем индексам для таблицы INSERT INTO #fraglist EXEC ('DBCC SHOWCONTIG (' + @tableidchar + ') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS') FETCH NEXT FROM tables INTO @tableidchar END -- Закрываем курсор CLOSE tables DEALLOCATE tables -- Для проверки выводим информацию из временной таблицы SELECT * FROM #fraglist -- Теперь необходимо произвести дефрагментацию -- Вначале опять объявляем курсор DECLARE indexes CURSOR FOR SELECT ObjectName, ObjectOwner = user_name(so.uid), ObjectId, IndexName, ScanDensity FROM #fraglist f JOIN sysobjects so ON f.ObjectId=so.id WHERE ScanDensity <= @maxfrag AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0 -- Выводим для проверки информацию о начале дефрагментации SELECT 'Started defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE()) -- Открываем курсор OPEN indexes -- Проходим циклом по всем индексам FETCH NEXT FROM indexes INTO @tablename, @objectowner, @objectid, @indexname, @frag WHILE @@FETCH_STATUS = 0 BEGIN SET QUOTED_IDENTIFIER ON SELECT @execstr = 'DBCC INDEXDEFRAG (' + @dbname + ', ' + RTRIM(@tablename) + ', ' + RTRIM(@indexname) + ') WITH NO_INFOMSGS' SELECT 'Выполняем: ' + @execstr; if @whatif <> 'whatif' EXEC (@execstr); --Обновление Статистики --> SELECT @execstr = 'UPDATE STATISTICS '+RTRIM(@tablename) + ' ' + RTRIM(@indexname) PRINT 'Выполняем UPDATE Статистика: ' + @execstr; if @whatif <> 'whatif' EXEC (@execstr); ------------------------<-- SET QUOTED_IDENTIFIER OFF FETCH NEXT FROM indexes INTO @tablename, @objectowner, @objectid, @indexname, @frag END -- Затем закрываем курсор CLOSE indexes; DEALLOCATE indexes; -- Отчитываемся о времени завершения SELECT 'Finished defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE()); -- Удаляем временную таблицу DROP TABLE #fraglist; |
|||
17
serpentt
30.05.19
✎
13:47
|
ПЕрвый раз конечно долго статистика восстанавливается. потом уже быстро работает и не напрягает
|
|||
18
ДенисЧ
30.05.19
✎
13:49
|
(16) Так это у вас дефрагментация индексов по необходимости, а не обновление статистики
|
|||
19
serpentt
30.05.19
✎
13:50
|
Это и дефрагментация и обновление статистики
Выполняем: DBCC INDEXDEFRAG (t14, SC6049, PCODE) WITH NO_INFOMSGS Выполняем UPDATE Статистика: UPDATE STATISTICS SC6049 PCODE [SQLSTATE 01000] |
|||
20
trad
30.05.19
✎
13:56
|
(19) у автора вопрос не как, а когда
|
|||
21
serpentt
30.05.19
✎
13:57
|
(20)У процедуры есть параметр, процент Дефрагментации.
|
|||
22
Mikeware
30.05.19
✎
14:25
|
может, как вариант. снять статистику фрагментации индексов при начавшихся тормозах, обновить индексы и статистику, и смотреть на степень фрагментации индекса? при превышении порога фрагментации - дефраг+упдстат?
|
|||
23
trad
30.05.19
✎
16:28
|
как раз индекс может быть не сильно фрагментирован, когда я залил значения которые сформировали новую ветвь дерева индекс, но при этом статистика сильно пострадает
|
|||
24
leonidkorolev
30.05.19
✎
17:39
|
(0) "Как проверить что не обновлена статистика в скуле?"
Что будет критерием того, что стата протухла? Дата последнего обновления, т.е. типа давно не обновлялась? Или что статистические данные не соответствуют реальным данным в индексе? Я сейчас как раз этим занимаюсь. База полтара тера, обновление статы более 10 часов. Думаю по дате ориентироваться. Обновлять если дата например больше двух дней. Вот начал писать скрипт. Кол дней получаю. use db select datediff(day,STATS_DATE(st.object_id, st.stats_id),GETDATE()) days,STATS_DATE(st.object_id, st.stats_id),* from sys.stats st join sys.objects ob on st.object_id=ob.object_id where type='u' |
|||
25
dk
31.05.19
✎
10:30
|
(24) пока думаю набор тестовых запросов с замером времени
проблема в том что несколько баз на 2000 скуле |
|||
26
ДенисЧ
31.05.19
✎
10:34
|
(24) А если у тебя таблица банковских счетов, которые добавляются раз в месяц? Тоже будешь апдейтить?
Нужно не просто по времени, а по частоте использования... |
|||
27
dk
31.05.19
✎
11:26
|
ну вот например сейчас подтупливает база - есть подозрение на const таблицу - в мониторинге эти запросы показывает по крайней мере
https://i.ibb.co/9v4jVCH/image.png а дату статы показывает сегодняшнюю |
|||
28
leonidkorolev
31.05.19
✎
12:19
|
(27) В таблице const что храниться? Константы? Они же не должны по идее меняться.
Это же константы. Соотв. статистика по ним не меняется. Статистика это же типа количество строк, гистограммы. Похоже дела не в статистике. |
|||
29
leonidkorolev
31.05.19
✎
12:21
|
(26) И даже не по частоте использования.
Перезапускают 1000 раз один и то же расчет себестоимости. С т.з. статистики ничего не меняется. Данные записываются одни и те же. Гистограммы одни и те же. А индексы все развалились. |
|||
30
dk
31.05.19
✎
12:27
|
(28) периодические реквизиты там
|
|||
31
Mikeware
31.05.19
✎
12:58
|
(28) Периодика там хранится.
что хреново сделано. |
|||
32
leonidkorolev
31.05.19
✎
13:01
|
Прикольную тему нашёл на просторах интернета.
rowmodctr - Подсчитывает общее количество вставленных, удаленных или обновленных строк, начиная с момента последнего обновления статистики для таблицы. select OBJECT_NAME(si.id),si.rowmodctr,* from sysindexes si order by si.rowmodctr desc |
|||
33
trad
31.05.19
✎
13:02
|
(27) тупить ведь может не по причине не актуальной статистики, а по причине хренового запроса
|
|||
34
Mikeware
31.05.19
✎
13:21
|
(33) ну, Данила вроде не самый глупый зверь в нашем зоопарке...
ну и к том же у него не "тупит постоянно", а "начинает тупить", а при пересчете статы - перестает |
|||
35
trad
31.05.19
✎
14:37
|
(34) "а при пересчете статы - перестает"
нет информации, что это утверждение применимо к случаю (27) |
|||
36
leonidkorolev
31.05.19
✎
14:43
|
Запилил скриптик. Выношу на общее обсуждение.
Обновление статистики у таблиц у которых было хотя бы одно изменение строки, вставка или удаление. use db declare @tablename varchar(1000) DECLARE @command nvarchar(4000); DECLARE tab_cursor CURSOR FOR select OBJECT_NAME(si.id) from sysindexes si join sys.objects so on si.id= so.object_id where so.type='u' and si.rowmodctr>0 group by OBJECT_NAME(si.id) order by OBJECT_NAME(si.id) OPEN tab_cursor FETCH NEXT FROM tab_cursor INTO @tablename WHILE @@FETCH_STATUS = 0 BEGIN set @command = 'update statistics dbo.'+ @tablename+' with fullscan, maxdop=0' print @command exec(@command); FETCH NEXT FROM tab_cursor INTO @tablename end close tab_cursor deallocate tab_cursor |
|||
37
dk
31.05.19
✎
15:54
|
похоже проблема в том что отработало ежедневное обновление статы, но пока не расковырял с какими параметрам наш админ все настроил
может там небольшой процент пересчета задан |
|||
38
ADirks
07.06.19
✎
11:23
|
Одно из лучших, на мой взгляд, решений
Рекомендую. Если не взять, то хотя бы посмотреть. Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |