Имя: Пароль:
1C
1C 7.7
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
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
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.