При интеграции 1С с внешними базами данных часто возникает ситуация, когда запрос к многомиллионной таблице (например, реестру недействительных паспортов, базе чеков или логов) выполняется крайне медленно. В ряде случаев более 95% времени уходит именно на ожидание ответа от СУБД внешнего источника. Разберем по шагам, почему это происходит и как кардинально оптимизировать производительность выборки.
Выясним причину задержки: когда во внешней таблице MS SQL насчитывается 100+ миллионов строк, а поиск выполняется по полям без подходящего индекса, СУБД вынуждена сканировать всю таблицу целиком (операция Table Scan или Clustered Index Scan). Это приводит к колоссальной нагрузке на дисковую подсистему и процессор сервера.
Для исправления ситуации выполним индексацию полей поиска во внешней базе данных через SQL Server Management Studio (SSMS):
Номер и Серия). При этом поле с большей селективностью (уникальностью значений) рекомендуется ставить первым.Посмотрим на пример DDL-запроса для создания такого индекса в MS SQL Server:
CREATE NONCLUSTERED INDEX [IX_Passports_Number_Series]
ON [dbo].[InvalidPassports] ([PassNumber] ASC, [PassSeries] ASC);
После создания индекса СУБД перейдет от полного сканирования таблицы к точечному поиску по дереву индекса (операция Index Seek), что сократит время выполнения запроса с минут до долей секунды.
Проанализируем правила взаимодействия платформы 1С с внешними источниками данных (ВИД), которые необходимо соблюдать для максимального быстродействия:
Справочник.ФизическиеЛица) и таблица внешнего источника данных, внешняя СУБД не может выполнить соединение на своей стороне. Платформа 1С будет выгружать данные на сервер 1С и соединять их во временных таблицах. Чтобы исключить падение производительности, выборку из внешнего источника следует выполнять отдельным запросом.ГДЕ (Поле1, Поле2) В (&СписокЗначений).Запрос. Это позволяет MS SQL Server кэшировать скомпилированный план выполнения (Execution Plan) и повторно использовать его при последующих вызовах.Посмотрим на пример правильной организации пакетного запроса к таблице внешнего источника данных в коде 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВнешняяТаблица.Серия КАК Серия,
| ВнешняяТаблица.Номер КАК Номер
|ИЗ
| ВнешнийИсточникДанных.ВнешняяБД.Таблица.НедействительныеПаспорта КАК ВнешняяТаблица
|ГДЕ
| (ВнешняяТаблица.Номер, ВнешняяТаблица.Серия) В (&СписокДокументов)";
Запрос.УстановитьПараметр("СписокДокументов", МассивПараметров);
Результат = Запрос.Выполнить().Выгрузить();
Если таблица содержит сотни миллионов строк и активно растет, рассмотрим дополнительные инженерные решения на стороне СУБД:
VARCHAR, NVARCHAR) для хранения числовых реквизитов существенно раздувает размер индекса. Объединение серии и номера в единое целочисленное поле типа BIGINT уменьшает индекс в несколько раз, позволяя ему целиком помещаться в оперативной памяти (Buffer Pool).PAGE Compression) для таблицы и некластерного индекса снижает объем дискового ввода-вывода и ускоряет чтение данных.MEMORY_OPTIMIZED обеспечивает время отклика в микросекунды.Разберем альтернативные подходы, если прямой опрос реляционной базы создает избыточную нагрузку:
Set или битовых карт в Redis гарантирует мгновенную проверку наличия ключа под любой параллельной нагрузкой.