Ускорение 1С, оптимизация, как ускорить работу 1С
Меню

Ускорение 1С: оптимизация, повышение скорости работы

Содержание статьи
  1. Блокировки в 1С 8.3: поиск и устранение в коде, перевод на управляемые блокировки
  2. 1С Управляемые блокировки
  3. Использование объектов DMO SQL-сервера
  4. Определение проблемных запросов в результате сбора Data Collector
  5. Оптимизация запросов как возможность ускорить 1С 8.3
  6. Использование индексов и их влияние на качество производительности системы

Во многом оптимизация 1С и скорость работы зависит от работы с блокировками, запросами и индексами. Постараемся ответить на вопрос «как ускорить работу 1С» (вопрос, как ускорить запуск 1С, мы рассмотрим в другой статье) и избежать жалоб пользователей на «долгое проведение документов», которое неминуемо сказывается на бизнес-процессах.

Блокировки в 1С 8.3: поиск и устранение в коде, перевод на управляемые блокировки

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

Концепция ACID
Концепция ACID

В автоматическом режиме управление блокировками осуществляется самой СУБД. При этом на MS SQL сервере появлялись такие побочные эффекты, как блокировки пустых таблиц и приграничного диапазона данных (уровень Serializable), что создавало дополнительные проблемы в многопользовательской работе. Для решения этих проблем фирма 1С создала управляемые блокировки.

1С Управляемые блокировки

Механизм блокировок был вынесен на сервер 1С, а на уровне СУБД изоляция снизилась до минимума. На MS SQL уровень изоляции был понижен до Read Committed с механизмом разделяемых блокировок на платформе 8.2 и механизмом версионирования строк на платформе 8.3 (так называемый Read Committed Snapshot Isoliation). Точнее, это одноименное свойство базы данных и два режима работы Read Committed, зависящие от этого параметра.

При последнем уровне изоляции (RCSI), механизм позволил не пересекаться на сервере СУБД читающих и пишущих транзакций по одним и тем же ресурсам. Всю основную работу на себя взял сервис блокировки 1С, определяющий на основании родных метаданных, пускать или не пускать транзакции на сервер СУБД, чтобы не происходило нарушений бизнес-логики. Проблемы с блокировками пустых таблиц и приграничных диапазонов ушли в прошлое.

СУБД Вид блокировки Уровень изоляции транзакций Чтение вне транзакции
Автоматические блокировки
Файловая База Данных Таблиц Serializable Dirty read
MS SQL Server Записей Repetable Read или Serializable Dirty read
IBM DB2 Записей Repetable Read или Serializable Dirty read
PostgreSQL Таблиц Serializable Consistent reading
Oracle Database Таблиц Serializable Consistent reading
Управляемые блокировки
Файловая База Данных Таблиц Serializable Dirty read
MS SQL Server 2000 Записей Read Commited Dirty read
MS SQL Server 2005 и выше Read Commited Snapshot Consistent reading
IBM DB2 до версии 9.7 Записей Read Commited Dirty read
IBM DB2 версии 9.7 и выше Записей Read Commited Consistent reading
PostgreSQL Записей Read Commited Consistent reading
Oracle Database Записей Read Commited Consistent reading

Для того чтобы узнать, в каком режиме блокировок находится база программы 1С, необходимо выполнить следующий запрос из SSMS в контексте нужной базы:

Запрос из SSMS в контексте нужной базы
Запрос из SSMS в контексте нужной базы

Блокировки 1С. Пользователь не будет ждать на блокировках, произойдет ускорение работы 1С, если придерживаться определенных правил:

  • Продолжительность транзакций должна быть максимально сокращена по времени. Проведение в транзакции длительных расчетов в 100% случаев приведет к блокировке при работе на OLTP системе.
  • Исключены длительные внешние операции в рамках транзакции, например, отправка и принятие подтверждений по электронной почте, работа с файловой системой и другие дополнительные действия. Все операции должны быть вынесены в отложенные короткие задания.
  • Максимально оптимизированы запросы.
  • Создание индексов должно производиться только по мере необходимости, для обеспечения оптимальной производительности запросов в пределах приложения.
  • Минимизированы включения в кластерный индекс часто обновляемых столбцов. Обновления столбца/ов кластерного ключа индекса требует блокировки, как на кластерном индексе, так и на всех некластеризованных индексах (так как их строка-локатор содержит ключ кластерного индекса).
  • По возможности создан и используется покрывающий индекс для сокращения времени выборки данных.
  • Использование самого низкого уровня изоляции транзакциями, что потребует перехода на режим управляемых блокировок.

Инструменты для диагностики блокировок:

  • Технологический журнал;
  • Центр управления производительностью из инструментария 1С;
  • Облачные сервисы Гилева;

Ниже приведен пример мониторинга системы сервисом Гилева. Общая длительность блокировок ~15 часов. Более 400 активных пользователей. После принятия решений и оптимизации – время таймаутов меньше минуты, а количество блокировок сократилось в ~670раз.

Было:

Пример мониторинга системы сервисом Гилева
Пример мониторинга системы сервисом Гилева

Стало:

Пример мониторинга системы сервисом Гилева
Пример мониторинга системы сервисом Гилева

В ситуации, когда «все висит и долго проводиться», а сервисы мониторинга не настроены или не используются совсем, помня принцип Парето, необходимо сосредоточить внимание на коде.

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

Системная процедура
Системная процедура

Доработав процедуру под 1С, можно получить наглядную информацию о том, что происходит в данный момент на сервере, с учетом специфики таблиц 1С:

Информация о сервере
Информация о сервере

Фрагмент 1


//Блокировки в терминах 1С
SELECT * FROM dbo.ReturnLockName1С(DEFAULT,DEFAULT) as t
Where TableName1С IS NOT NULL
ORDER BY t.Resource

Применение данного механизма позволяет получить полную информацию об имеющихся блокировках на текущий момент. Если в отчете одни S-блокировки, проблема может заключаться в длительном запросе или запросах. Для установления причины и места их появления в коде можно пойти разными путями: использовать объекты DMO SQL-сервера (но учитываем, что данные из них сбрасываются после перезагрузки сервера) или настроить Data Collector, сохранив данные мониторинга в таблицах на определенное время. Главное, получить тексты проблемных запросов.

Использование объектов DMO SQL-сервера

Выводим дату старта сервера для понимания актуальности данных. Разбиваем пакет по рейтингу чтения (физического, логического, нагрузке на процессор). В этом случае используются основные данные из sys.dm_exec_query_stats. Текст запроса переводим в термины 1С. Если по тексту запроса можно понять контекст вызова, то осталось посмотреть план запроса, найти проблемные операторы и понять, что можно сделать.

Актуальные данные
Актуальные данные

Фрагмент 2


//время запуска
SELECT sqlserver_start_time
FROM sys.dm_os_sys_info;

//Toп запросов no физическому чтению
SELECT TOP (50)
(total_physical_reads ) AS Итого_физическое_чтение,

Запрос
Запрос

Определение проблемных запросов в результате сбора Data Collector

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

Результат сбора Data Collector
Результат сбора Data Collector

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

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

Пример проблемного запроса и образец настройки технологического журнала:

Пример проблемного запроса
Пример проблемного запроса

Образец настройки технологического журнала
Образец настройки технологического журнала

Оптимизация запросов как возможность ускорить 1С 8.3

Рассмотрим основные рекомендации, соблюдение которых позволит увеличить скорость работы 1С путем уменьшения проблем в написании запросов.

Базовая схема улучшения производительности неоптимального запроса
Базовая схема улучшения производительности неоптимального запроса

Последствия неоптимальных запросов могут проявляться в виде длительных проведений документов, мучительно долгого формирования отчетов, «зависания» системы и прочих неприятных событий.

При работе с запросами НЕЛЬЗЯ:

  • Соединять таблицы с подзапросами;
  • Соединять обычные таблицы с виртуальными;
  • Использовать логического «ИЛИ» в условиях;
  • Использовать подзапросы в условиях соединения;
  • Получать данные через точку от полей составного типа без ключевого слова «Выразить».

При работе с запросами МОЖНО:

  • Создать индексы в условиях запроса, полях соединения, агрегации и сортировки;
  • Фильтрацию виртуальных таблиц необходимо производить с использованием параметров отбора.

Использование индексов и их влияние на качество производительности системы

Очень много написано про индексы, о необходимости их использования и влияние на качество работы системы. Постараемся разобраться в тонкостях «устройства» индексов, вариантах применения и преимуществах перед обычными таблицами.

Индексирование является важной частью ядра СУБД. Отсутствующие индексы, или наоборот, их излишнее количество, влияют на скорость выборки, модификацию, добавление и удаление данных. Рассмотрим индексирование на примере наиболее распространенной СУБД компании Microsoft.

Для общего понимания, как это работает, рассмотрим подробности устройства механизмом хранения данных, которые мы обычно представляем в виде таблицы (например, Excel).

Единицей физического хранения данных является страница — модуль размером в 8 Кбайт, принадлежащий только одному объекту (например, таблице или индексу). Страница является наименьшей единицей для чтения и записи. Страницы собраны в экстенты. Экстент состоит из 8 последовательных страниц. Страницы экстента могут принадлежать как одному, так и нескольким объектам. Если страницы принадлежат нескольким объектам, экстент называется «смешанным».

Заголовок страницы (первые 96 байт) состоит из разных флагов, которые использует в работе ядро СУБД. Ее содержимое можно посмотреть ниже:

Заголовок страницы (первые 96 байт) состоит из разных флагов, которые использует в работе ядро СУБД
Заголовок страницы (первые 96 байт) состоит из разных флагов, которые использует в работе ядро СУБД

Строки с данными (8060 байт): 

Строки с данными (8060 байт)
Строки с данными (8060 байт)

Таблица смещения (36 байт):

Таблица смещения (36 байт)
Таблица смещения (36 байт)

Получив представление, как устроена единица хранения данных на диске, поговорим подробнее о таблицах и индексах.

По умолчанию, если не использовать специальных операторов T-SQL, пустая таблица создается в виде «кучи» – простого набора страниц и экстентов. Данные в «куче» не имеют никакого логического порядка. Ядро SQL Server отслеживает принадлежность страниц и экстентов к определенному объекту с помощью специальных системных страниц, называемых «картами распределения индекса» (Index Allocation Map). Каждая таблица или индекс имеет по крайней мере одну страницу IAM, называемую «первой страницей IAM».

Страница IAM
Страница IAM

Таким образом, после создания обычной таблицы, по умолчанию, получается хаотичное расположение данных. Посмотреть статус таблицы можно с помощью следующей процедуры:

Процедура
Процедура

Основные индексы, которые использует платформа 1С

Фрагмент 3


SELECT NAME, TYPE, TYPE_DESC FROM sys.indexes WHERE object_id = OBJECT_ID('ДанныеТрассировки')

Мифы и реальность:

Миф первый: кластерные индексы и таблица данных – это две разные сущности, хранящиеся отдельно друг от друга.

Миф второй: кластерных индексов в одной таблице может быть много.

Скачал программу для оптимизации СУБД. Создал рекомендованные индексы. Скорость выборки увеличилась на 50%. Изменение и добавление данных замедлилось в 7раз.

Кластеризованный (кластерный) индекс

Кластеризованные индексы представляют собой набор страниц, которые сортируют и хранят строки данных в таблицах или представлениях на основе их ключевых значений – столбцов, включенных в определение индекса. Существует ограничение на данный вид индексов в 16 столбцов и 900 байт. Для каждой таблицы существует только один кластеризованный индекс, потому что строки данных могут быть отсортированы только в одном порядке. Создание кластеризованного индекса происходит посредством реорганизации таблицы, а не копирования данных, что дает возможность сохранить таблицу в виде сбалансированного дерева.

После добавления кластерного индекса таблица данных трансформируется:

После добавления кластерного индекса таблица данных трансформируется
После добавления кластерного индекса таблица данных трансформируется

Фрагмент 4


SELECT NAME, TYPE, TYPE_DESC FROM sys.indexes WHERE object_id = OBJECT_ID('ДанныеТрассировки')

Некластеризованный индекс

Некластеризованные индексы имеют структуру отдельную от строк данных. В некластеризованном индексе содержатся значения ключа кластерного индекса, и каждая запись содержит ключ кластеризованного индекса (не RID, т.к. таблицы 1С не используют кучи, за редким исключением).

Можно добавить неключевые столбцы на конечный уровень некластеризованного индекса и обойти существующее ограничение на ключи индексов (900 байт и 16 ключевых столбцов), выполняя полностью индексированные запросы.

После добавления некластерного индекса, произошло копирование данных, и появился еще один объект:

После добавления некластерного индекса, произошло копирование данных
После добавления некластерного индекса, произошло копирование данных

Фрагмент 5


SELECT NAME, TYPE, TYPE_DESC FROM sys.indexes WHERE object_id = OBJECT_ID( 'ДанныеТрассировки')

Схема кластерного индекса после получения его из кучи в виде сбалансированного дерева:

Схема кластерного индекса после получения его из кучи
Схема кластерного индекса после получения его из кучи

Схема некластерного индекса, полученного из кластерной таблицы (обратите внимание, столбец row locator имеет ключ кластерного индекса):

Схема некластерного индекса, полученного из кластерной таблицы
Схема некластерного индекса, полученного из кластерной таблицы

Влияние индексов на производительность запросов

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

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

Обратим внимание, что кластерный индекс блокировать ни в коем случае нельзя, т.к. это закроет доступ к данным таблицы. Это относится только к тем индексам, которые вы создали самостоятельно, через T-SQL. Причина создания индексов средствами T-SQL, минуя «1С:Предприятия», связана, в первую очередь, с ограниченными возможностями платформы 1С в части манипуляции индексами и включения в созданный/емый индекс дополнительных полей.

Инструкция T-SQL, которая выполняет действие по блокированию индекса:


//Блокируем отдельный индекс в таблице
-ALTER INDEX  _Reference22_ByPredefinedIDNotUniq ON _Reference22
 DISABLE;

//Включаем нужный индекс
-ALTER INDEX  _Reference22_ByPredefinedIDNotUniq ON _Reference22
 REBUILD;

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

Определение необходимых или лишних индексов для ускорения выполнения запросов

По умолчанию 1С создает определенный базовый набор индексов. Зачастую, их просто не хватает. SQL-сервер имеет механизмы, которые позволяют понять на основании рабочей нагрузки, насколько необходимы имеющиеся индексы.

Помощник по настройке ядра СУБД (Database Engine Tuning Advisor) анализирует базы данных и составляет рекомендации по оптимизации производительности запросов. Его можно использовать для выбора и создания оптимальных наборов индексов, не обладая экспертным уровнем понимания структуры баз данных или внутренних процессов SQL Server. Помощник по настройке ядра СУБД позволяет выполнять следующие задачи:

  • Устранение неполадок производительности конкретного проблемного запроса;
  • Настройка большого набора запросов в одной или нескольких базах данных.

Объекты DMO (dynamic management objects), к которым относятся динамические административные представления и функции динамического управления. Например, инструкцией T-SQL можно получить все индексы, которые не использовались с момента последнего запуска сервера.

Индексы, которые не использовались с момента последнего запуска сервера
Индексы, которые не использовались с момента последнего запуска сервера

Фрагмент 6


WITH vl as (
   SELECT OBJECT_NAME(I.object_id) AS objectname,
   I.name AS indexname, I.index_id AS indexid
   FROM sys.indexes AS I
   INNER JOIN sys.objects AS O
   ON O.object_id = I.object_id
   WHERE I.object_id > 100
   AND I.type_desc = 'NONCLUSTERED' AND I.index_id NOT IN
   (SELECT S.index_id
   FROM sys.dm_db_index_usage_stats AS S

  WHERE S.object_id=I.object_id
  AND I.index_id=S.index_id
  AND database_id = DB_ID('Имя_базы’)))

  SELECT objectname,T1.NameTable1С, indexid, indexname
  FROM vl
  OUTER APPLY dbo.ReturnTableName1С(objectname) as T1
  ORDER BY objectname, indexname;

Инструкция, с помощью которой можно создавать необходимые индексы, которые рекомендует ядро СУБД:

Инструкция, с помощью которой можно создавать необходимые индексы
Инструкция, с помощью которой можно создавать необходимые индексы

Фрагмент 7


SELECT
T1.NameTable1С as Наименование_таблицы_1С,
'CREATE INDEX [missing_index_'
+ CONVERT (VARCHAR, mig.index_group_handle) + '_'
+ CONVERT (VARCHAR, mid.index_handle) + '_'
+ LEFT(PARSENAME(mid.statement, 1), 32) + ']' + ' ON '

Оптимизатор запросов во время генерации плана выполнения запроса выявляет необходимость создания недостающего индекса. Эту информацию он сохраняет в XML ShowPlan. Т.к. планы запросов хешируются и инструкции сохраняются (до следующего перезапуска сервера), то их можно извлечь, обработать и получить готовые инструкции создания необходимых индексов для любого плана выполнения в кэше. Стоит обратить внимание на частоту выполнения запроса: чем она выше, тем более актуальными являются результаты выполнения запроса и, соответственно, собранные показатели. Если запрос выполнялся единожды, его результаты не столь показательны.

Оптимизатор запросов во время генерации плана выполнения запроса выявляет необходимость создания недостающего индекса
Оптимизатор запросов во время генерации плана выполнения запроса выявляет необходимость создания недостающего индекса

Информация в XML ShowPlan
Информация в XML ShowPlan

Фрагмент 8


CROSS APPLY query_plan.nodes(’//StmtSimple') AS stmt(stmt_xml)
WHERE stmt_xml.exist('QueryPlan/Missinglndexes') = 1
)
SELECT TOP 30
DatabaseName as Наименование_базы,
TableName as Наименование_таблицы,
T1.NameTable1С as Наименование_таблицы_1С,
equality_columns as Столбцы_сравнения,
include_columns as Столбцы_для_включения,

Имя базы
Имя базы

Фрагмент 9


USE [Имя_базы]
GO
 CREATE NONCLUSTERED INDEX []
 ON [dbo].[_Document497] ([_Fld12771_TYPE],[_Fld12771_RTRef])
 INCLUDE ([_Date_Time],[_Fld12771_RRRef],[_Fld12782RRef],[_Fld12784])
GO

Некоторые особенности индексирования по агрегатным полям и полям сортировки.

Создание индекса на столбцах, указанных в предложении «УПОРЯДОЧИТЬ ПО» (ORDER BY), помогает оптимизатору запроса быстро организовать результирующий набор данных, так как значения столбцов отсортированы в индексе заранее. Внутренняя реализация механизма «СГРУППИРОВАТЬ ПО» (GROUP BY) также сначала сортирует значения столбцов для быстрой группировки необходимых данных.

При использовании типовых рекомендаций стоит проверять результат до и после оптимизации. Приведем пример использования логического объединения «ИЛИ» и его альтернативы (для устранения проблемы типовыми рекомендациями) – методики изменения запроса через синтаксис «ОБЪЕДИНИТЬ ВСЕ».

Сам запрос 1С с «ИЛИ»:


ВЫБРАТЬ Код, Наименование, Ссылка
ИЗ
     Справочник.Контрагенты КАК Контрагенты
ГДЕ
    Контрагенты.Код = "000000004"
    ИЛИ Контрагенты.Код = "0074853"
    ИЛИ Контрагенты.Код = "000000024"
    ИЛИ Контрагенты.Код = "009679294"
    ИЛИ Контрагенты.Код = "0074742"
    ИЛИ Контрагенты.Код = "000000104";

Модификация запроса с «ОБЪЕДИНИТЬ ВСЕ»:


ВЫБРАТЬ Код, Наименование, Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ГДЕ
    Контрагенты.Код = "000000004"
    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ Код, Наименование, Ссылка
ИЗ
   Справочник.Контрагенты КАК Контрагенты
ГДЕ
   Контрагенты.Код = "0074853"
   ОБЪЕДИНИТЬ ВСЕ

   ВЫБРАТЬ Код, Наименование, Ссылка
ИЗ
   Справочник.Контрагенты КАК Контрагенты
ГДЕ
   Контрагенты.Код = "000000024"
   ОБЪЕДИНИТЬ ВСЕ

   ВЫБРАТЬ Код, Наименование, Ссылка
ИЗ
   Справочник.Контрагенты КАК Контрагенты
ГДЕ

Фактический план запроса (для удобства отображения и сравнения производительности, запросы перехвачены и выполнены в SSMS):

Фактический план запроса
Фактический план запроса

В данном случае, после оптимизации производительность упала в два раза из-за многократного использования оператора Key Lookup, который всегда сопровождается оператором Nested Loops. Поэтому, используя схему по оптимизации запроса, следует замерять целевое время до и после использования доработок. Данный пример показан с целью «доверяй, но проверяй», поскольку между типовыми рекомендациями и практическими задачами может быть несогласованность.


Рассказать друзьям
Предыдущая статья статья
Вопросы переходного периода: ОФД, онлайн касса, № 54-ФЗ
Следующая статья статья
Создание и настройка внешней печатной формы в 1С
Комментарии