Быстрый фронт в базе размером 6.8 терабайт – наши стандарты при разработке и рефакторинге запросов

29.08.22

База данных - HighLoad оптимизация

От быстродействия запросов, которые обращаются к крупным таблицам, напрямую зависит скорость работы всей базы в целом. Артем Кузнецов, тимлид команды 1С в компании ООО «Финтех решения» на конференции Infostart Event 2021 Moscow Premiere рассказал, как оптимизировать производительность при поддержке больших систем. Показал, на что следует обращать внимание при код-ревью запросов, как оптимизировать RLS, виртуальные таблицы, индексы и условия, и как доработка архитектуры решения может ускорить работу базы.

Меня зовут Артем Кузнецов, я тимлид самого крупного МФО в России. Кроме обязанностей тимлида я также занимаюсь тем, что мне больше всего нравится в разработке. В частности, оптимизацией запросов и в целом кода – увлекаюсь этим в свободное время.

База у нас уже больше 7 терабайт. Мы прирастаем в неделю на 10-50 ГБ. Поэтому нам нужно разрабатывать так, чтобы фронт работал.

 

 

О чем пойдет речь в докладе?

  • Расскажу, зачем вообще оптимизировать код. Очень часто в 1С встречается подход, когда вместо того, чтобы уделить неделю или месяц разработки на рефакторинг, докупают железо. Потому что это проще. Железо купил, воткнул – код начал работать быстрее. Нам это уже не помогает. У нас хорошая корпоративная серверная по цене боинга. Мы себе уже все самое топовое железо купили, но оно уже не вывозит, поэтому мы смотрим в сторону оптимизации.

  • При разработке любых новых запросов, вне зависимости от их размера и сложности, мы всегда стараемся следить за соблюдением стандартов и проводить код-ревью. Потому что это вырабатывает привычку, а привычка – это самое главное. Когда человек по привычке уже пишет хорошо, и код-ревью быстро проходит, и система работает стабильно.

  • Еще расскажу про практику оптимизации при деградации легаси. Легаси у нас есть, еще до моего прихода в компанию появилось, и оно периодически деградирует. Например, какой-то запрос два года работал, не менялся, и потом почему-то вдруг взял и положил нам базу. Такое бывает сплошь и рядом. Разбираемся, что произошло, и оптимизируем.

 

Ключевая метрика

 

 

Ключевая метрика, на основании которой мы определяем, что нужно что-то оптимизировать – это так называемый «спидометр», которые выведен на отдельный большой экран. Такие экраны у нас висят на стене в отделе разработки, в техподдержке, у админов, у топ-менеджмента – у них тоже есть отдельный экран с таким спидометром.

У этого «спидометра» есть несколько состояний.

  • Первое состояние – нормальное, зеленое, когда все занимаются своими делами, спокойно работают в потоке. «Зеленый спидометр» характеризуется тем, что среднее время выполнения ключевых операций не превышает четырех секунд. Мы замеряем время всех операций, которые выполняют фронт-менеджеры на местах в офисах, и выводим на экран среднее значение. Этот показатель смотреть в моменте нет смысла, он обязательно должен смотреться на каком-то промежутке времени. Он может в какой-то момент подскочить в какую-то высокую красную зону. Но потом тут же вернуться обратно, это нормально.

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

 

 

  • Дальше – красная метрика – это все плохо. В чате техподдержки творится апокалипсис, у ИТ-директора и руководителя отдела разработки заплата начинает капать в обратную сторону. Все бросают свои дела и занимаются поиском проблем, подключаются разработчики, дополнительные люди, еще кто-то, чтобы хоть кто-то нашел причину и быстро с ней разобрался.

  • И, наконец, значение, к которому мы стремимся – эта метрика была снята в два часа ночи, причем, мне пришлось ее поискать в моменте просто для скрина. Но мы стремимся вот к этому мифическому единорогу, когда в праймтайм база работает в таком режиме. В этом случае нам, наверное, купят Playstation на отдел, мы сможем спокойно пить смузи и играть в Playstation целый день. Я очень надеюсь на это.

 

RLS

 

 

Первый блок, который нам сильнее всего аффектит базу на данный момент и в целом по истории – это RLS.

Система Record Level Security – это ограничение прав на уровне записи стандартное 1С-ное, стандартная система в базах данных.

Расскажу, как мы с ней работаем и какие у нас требования при работе с RLS

  • Мы используем ВЫБРАТЬ РАЗРЕШЕННЫЕ при любом обращении к физическим таблицам, даже если там нет сейчас RLS. Он может появиться, и все упадет. Поэтому «РАЗРЕШЕННЫЕ» должно быть всегда. Если нет RLS, оно не нагружает запрос. Даже если влияет, это настолько мизерно, что риски, что все упадет, гораздо выше.

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

  • Если из одного объекта (грубо говоря, из контрагента), нужно достать три поля, не нужно это делать в трех разных запросах пакета, соберите это в одном месте, это будет работать в три раза быстрее. Это действительно так.

  • У нас есть разыменование более одной точки, но оно допустимо только при последовательной индексации полей цепочки – в конкретном ограниченном списке ситуаций, которые для нас являются стандартными. В остальном мы не используем разыменования более одной точки. Используем соединения – внутреннее или левое, если нужно достать NULL. Через четыре-пять точек не разыменовываем, это плохо.

  • Кроме этого, когда мы обновились на БСП 3.1, у нас появилась проблема, что даже если для RLS установлен признак «Все разрешено», он все равно срабатывает, и начинают появляться вот эти дополнительные запросы к базе.

 

 

С точки зрения 1С RLS выглядит достаточно просто.

Есть регистр накопления, из него достаются какие-то поля.

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

Выглядит легко.

 

 

А это – то, что происходит уже на уровне запроса SQL. Это только половина запроса, даже чуть меньше, потому что все остальное даже не влезло на экран, я не стал мельчить. Это – то, что SQL выполняет при простом обращении к RLS по одному подразделению.

 

 

Наша самая большая проблема – это разыменования полей из таблиц во время запросов с RLS.

В таком случае количество выполнений запроса с ограничениями выльется в сотни тысяч миллионов раз на уровне SQL. В запросе это выглядит кратенько, красиво, но по факту получается 54 миллиона выполнений одного и того же запроса. 54 миллиона строк выбралось и для каждой из этих строк выполнился этот запрос. Это все из-за того, что у нас есть такие запросы в RLS.

Это очень тяжело, очень нагружает и систему, и, естественно, долго выполняется.

 

Нюансы поведения RLS

 

 

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

  • на справочнике Договоры есть RLS;

  • на регистре сведений УсловияДоговоров нет RLS;

  • на справочнике Подразделения и Команды тоже нет RLS.

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

 

 

Реальность:

  • Будут выбраны все записи из регистра, потому что это СрезПоследних.

  • В поле «Договор» будет значение «Объект не найден» для тех, у кого эти объекты недоступны

  • В поле Подразделение для недоступных пользователю договоров будет, естественно, NULL

  • При попытке разыменования NULL мы еще и получим исключение.

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

 

 

Решение достаточно простое – мы формируем предвыборку данных из справочника, и дальше делаем СрезПоследних, передавая внутрь среза эту предвыборку в виде временной таблицы и отбора. Так это работает и быстро, и без ошибок. И выбирает только то, что нужно. Потому что перед формированием виртуальной таблицы среза будет уже предвыбрана заранее таблица договоров, по которым она и будет формироваться.

 

Пример оптимизации RLS

 

 

На слайде запрос, который вроде выглядит как надо, но из-за того, что таблица «Договоры» использует RLS, этот запрос у нас выполняется больше 1800 секунд.

 

 

Как мы его оптимизировали? Мы убрали разыменование Договор.Подразделение в отборах виртуальной таблицы – выключили его, перенесли заранее через внутреннее соединение из той таблицы, которую мы передали изначально внутрь среза в отдельную временную таблицу. И далее уже эту временную таблицу передали в СрезПоследних.

И мы получили выполнение запроса вместо 30 минут – 1-2 секунды. Таким простым действием мы на порядки сократили время выполнения.

 

Виртуальные таблицы

 

 

Теперь кратко по виртуальным таблицам – наши требования:

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

  • Если из виртуальной таблицы Оборотов или ОстаткиИОбороты требуется какая-то часть данных (например, только Приход), их лучше собрать из физической таблицы. Это, как правило, работает быстрее, но не всегда. Все наши требования работают примерно в 95-97% случаев. Оставшиеся 3-5% выстреливают даже с учетом наших требований, и мы к ним имеем уже отдельные подходы, которые нарушают наши требования, но при этом работают тоже. Но изначально мы пишем так, потому что, как правило, это работает.

  • На больших объемах данных, когда больше миллиона строк в таблице не рекомендуется использовать виртуальную таблицу ОстаткиИОбороты – лучше все собирать вручную. По крайней мере, на нашей базе. Эти все правила применимы к нашей базе, у вас могут быть какие-то другие, а мы за три года выработали такой список.

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

  • МоментВремени мы используется только если действительно это нужно – как правило, хватает поля Период.

  • Не рекомендуется использовать условие Поле В(<Вложенный запрос>) в отборах виртуальных таблиц, если во вложенном запросе много элементов – это то, что вы видели на предыдущем слайде, когда я передавал временную таблицу в отбор виртуальной. Если во временной таблице много элементов, обратитесь к физической таблице, не используйте виртуальную. Используйте внутреннее соединение и дальше уже нужное вам агрегирование среза или еще что-то.

 

Примеры оптимизации для виртуальных таблиц

 

 

Регистр сведений, достаточно большой. В нем все наши телефонные звонки – у нас их достаточно много совершается каждый день.

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

 

 

Соответственно, здесь мы добавили дополнительный параметр &ПериодДляИтогов, экспортный метод в общем модуле. И проверяем, что если дата окончания больше или равна текущей дате, мы ее просто убираем, оставляем Неопределено, чтобы гарантировать использование готовой виртуальной таблицы, чтобы ее SQL заново не считал. Это значительно ускоряет работу во многих наших отчетах.

 

 

Еще пример – регистр СостоянияСобщенийSMSСрезПоследних.

SMS-ок у нас тоже много, при получении СрезаПоследних формируется неоптимальный запрос, что приводит к перебору 115 миллионов записей. В данном случае несмотря на то, что у нас есть отбор по идентификатору.

 

 

Тут мы просто сделали ручной срез на временных таблицах.

Главное – проиндексировать первую таблицу. Это тоже дает выигрыш – хоть и не на порядки, но в разы быстрее.

 

 

Еще запрос, который кушал очень много памяти.

В регистре накопления «Расчеты» хранятся все наши взаиморасчеты с контрагентами.

У нас есть отдельные регистры для каких-то конкретных направлений, а в регистре «Расчеты» лежит вообще все, что у нас происходит с договорами. В этом регистре сейчас более 500 миллионов записей.

Тут вроде просто получение остатков по концу периода, а дальнейшее внутреннее соединение – это к вопросу соединения с виртуальной таблицами. Если виртуальная таблица оказалась справа, мы получаем 70 гигабайт больше потребления памяти.

 

 

Решение – просто занести то, что было соединено, внутрь. Простое действие, но оно опять же, очень сильно ускоряет работу запроса.

 

Индексы

 

 

Теперь расскажу про важность индексации. Многие 1С-разработчики почему-то не любят использовать индексацию, не очень понимают, что это такое.

Наши требования касаемо индексации:

  • Мы всегда индексируем поля временных таблиц, которые участвуют в соединениях, при условии, что эта временная таблица может оказаться справа. Если она всегда гарантировано слева, то ее индексировать смысла нет, из нее выборка сама происходить не будет.

  • Все поля отборов (то, что в конструкции ГДЕ) при использовании ВНУТРЕННЕЕ СОЕДИНЕНИЕ, мы выносим обратно во ВНУТРЕННЕЕ, но если мы можем гарантировать, что среди отборов есть какой-то отбор с высокой селективностью, можно его только оставить в соединении, а все остальное вернуть обратно в ГДЕ. Если мы не уверены, лучше все засунуть во ВНУТРЕННЕЕ СОЕДИНЕНИЕ, планировщик разберется, выберет самый оптимальный, самый селективный отбор – поставит его первым и выполнит запрос быстро.

  • И использование по возможности кластерного индекса – это индекс на таблицы, который создает сама 1С. Он всегда есть изначально – на любых таблицах, даже если ни одного поля не проиндексировано, он всегда есть. На любом регистре, на любом документе. Соответственно при отборе, при соединении по кластерному индексу, это тоже работает очень быстро, потому что в кластерном индексе лежат все поля таблицы – он может оттуда выбрать все.

 

Примеры оптимизации для задействования индексов

 

 

Условие соединения в данном запросе не попало в индекс, соответственно, мы получили полное сканирование. Казалось бы, Договор – должно быть селективное поле, но, тем не менее, мы получили FullScan.

 

 

Решение – мы формируем предварительную выборку полей. Тут идет два обращения к физической таблице, но это работает сильно быстрее. Мы предварительно выбрали только поля кластерного индекса регистра по одному договору, потому что это наиболее селективное поле. И дальше снова соединились с регистром, но гарантированно попали в кластерный индекс. Все поля – Период, Регистратор, НомерСтроки – это как раз поля кластерного индекса. И добрали уже нужную нам сумму. Это начало работать гораздо быстрее.

За последний год я такими действиями оптимизировал примерно 20% всех запросов. Просто вынимаешь из запроса выборку по полям кластерного индекса, потом соединяешь ее внутренним соединением с физической таблицей регистра, добавляешь нужные поля. Стало быстрее? Сразу на прод.

Достаточно простое решение. Но оно помогает.

 

Условия в запросах

 

 

Для условий запросов есть достаточно хорошие стандарты 1С. Они есть и как правило работают – мы ими активно пользуемся. Но мы их немного ужесточили – именно для своей базы.

  • Все вычисляемые поля мы предварительно рассчитываем в секции «ВЫБРАТЬ», мы не используем отборы по вычисляемым полям. Даже когда есть какие-то математические операции, мы сначала их лучше во временной таблице выберем и вычислим в секции ВЫБРАТЬ, проиндексируем, если нужно. И потом уже отберем по ним. Это работает быстрее, чем сразу вычислять в условиях, потому что при вычислении в условиях вычисление происходит для каждой строки, что крайне долго.

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

  • Мы используем ЕСТЬ НЕ NULL вместо НЕ ЕСТЬ NULL. Казалось бы, вроде одинаковые конструкции, но ЕСТЬ НЕ NULL – это родная конструкция, которая работает гораздо быстрее.

  • За ИЛИ / В() у нас тимлиды отдела разработки готовы убивать, если кто-то это использует в запросах. Если это ИЛИ делаем через ОБЪЕДИНИТЬ, если это В() – через внутреннее соединение. Потому что тогда мы можем гарантировать использование индексов, мы можем управлять планом запросов, управлять тем, как это будет выполняться. И тем самым гарантировать стабильность – что это, по крайней мере, не деградирует.

  • Сравнение ТИПЗНАЧЕНИЯ()=ТИП() не используем, преобразуем в стандартный метод ССЫЛКА

  • Помним, что соединения – это тоже условия, к ним применимы все те же правила, которые для секции ГДЕ

  • И явные соединения со вложенными запросами у нас запрещены – мы не используем соединения со вложенными запросами ни в каком виде. Предвыборка во временную таблицу, индексация и только потом соединение.

 

Примеры оптимизации для условий запросов

 

 

Документ «Заявка» – это наш ключевой документ, с которым работают пользователи.

Этот запрос выполняется при интерактивной работе, когда менеджер ищет клиента в базе. Он занимал 10 секунд. Т.е. клиент пришел, сказал ФИО, дату рождения, его начали искать в базе, он 10 секунд ждет, пока выполнится этот запрос и менеджер его найдет в базе. Это не единственный запрос, который там выполняется, но этот был самый долгий.

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

 

 

Что мы сделали?

Мы сократили время выполнения этого запроса с 10 секунд до менее чем полсекунды.

Это стало возможным за счет того, что мы вынесли НЕ в предвыборку справочника и внутреннее соединение.

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

Перечисление – тоже выборка быстрая, В() использовать допустимо.

И дальше – два внутренних соединения.

Почему не проиндексированы первые две таблицы? Потому что они гарантированно маленькие и крайне маловероятно, что СУБД поставит их справа, они практически со 100% вероятностью будут слева, поэтому накладные расходы на индексацию конкретно здесь не оправданы.

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

А оставшиеся отборы работают достаточно быстро.

 

Работа с архитектурой решения

 

 

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

Рекомендации, которые мы стараемся поддерживать:

  • Во-первых, мы анализируем использование полей таблиц в условиях. У нас есть ходовой регистр, к которому обращаются много отчетов. И мы, например, находим, что из трех измерений регистра чаще всего используется первое и третье, а второе используется редко. При этом кластерный индекс содержит в себе все три измерения, и при использовании первого и третьего кластерный индекс не используется. Просто поменяв второе и третье местами, мы, не изменив ни строчки кода, ускорили 15-20% фронтовых отчетов. Да, потребовалась реструктуризация, но она влезла в технологическое окно и ускорила нам базу в два клика – очень удобно.

  • Если вы в запросах рассчитываете одни и те же данные, которые не динамические, а статичные изо дня в день (они не зависят от фазы луны, от времени года и всего остального), лучше их рассчитать – регламентно рассчитывать заранее и куда-то складывать. Да, это дополнительное место, это размер базы, но обращаться к готовым данным в разы быстрее, чем считать их «на лету». Считать на лету – крайне плохо с нашей точки зрения, и мы все, что можно вынести в предрасчет и где-то хранить заранее, и потом уже оттуда доставать, мы все выносим.

  • Дальше – если у вас есть большая таблица, из которой стабильно выбирается 3-5% строк, а все остальные 95% строк в отчетах почти никому не нужны (например, они нужны только для каких-то регламентных операций). Соответственно, мы выносим эти 3-5% в отдельную таблицу. В старой таблице их тоже оставляем, но делаем рядом еще одну, которую клонируем и ужимаем – оставляем только эти нужные данные. Да, это время на дозаполнение данных, это объем базы, но это того стоит, если используется часто, и таблицы большие изначально.

  • Включение итогов – тут понятно, что предрасчитанные виртуальные таблицы – это быстро. Да, итоги – это тоже дополнительные таблицы в базе. Но если к ним часто идет обращение, то используем.

  • Стараемся не использовать флаг «Активность», потому что он не индексирован. И чтобы выбрать из 500 миллионов записей 99,9%, у которых есть этот флаг, и 1-2 записи, у которых нет этого флага – не имеет смысла, это, опять же, будет перебор.

  • И ручное создание индексов в SQL по рекомендациям DBA – это запрещено лицензионным соглашением 1С, и мы стараемся его тоже не использовать или использовать временно, до того, как мы найдем какое-то другое решение – это только в крайнем случае. Но оно тоже имеет место быть, тоже ускоряет, от этого никуда не деться.

 

Примеры оптимизации для доработки архитектуры решения

 

 

ЖурналЗвонков – это регистр сведений, который мы уже смотрели. В нем около 150 миллионов записей.

Данный запрос – это программный срез последних – выполнялся 35 секунд. Причем соединение по индексированному полю, идентификатору ИДВзаимодействия, селективность стремится к единице.

 

 

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

Но это работает только если таблица итогов будет гарантировано использоваться – при пустом периоде. Если таблица итогов используется негарантировано, тут надо уже дважды подумать.

И запрос стал выполняться две секунды вместо 35 – ускорение в 15 с лишним раз.

 

Заключение

 

 

В заключение доклада рекомендую вам – кто раньше писал не по стандартам, забыть это и переходить на стандарты.

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

И дальше уже по этому примеру рефакторьте старое.

 

Вопросы

 

Как проверять правильность написания запроса? Только глазами, через код-ревью или с помощью SonarQube?

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

Вопрос про временные таблицы. Я как руководитель группы разработки замечаю повальное использование временных таблиц разработчиками, потому что фирма «1С» в своем стандарте говорит: «Нужно использовать временные таблицы». Правда она потом говорит, что их нужно использовать «...только тогда, когда...». А еще потом говорит, что их не должно быть много. Но временные таблицы же не по факту временные, они все равно физические, и, если таблица большая она пишется во время выполнения в tempdb, которая находится на диске или в оперативке. Есть ли у вас какие-то критерии, когда вы категорически не рекомендуете разработчикам использовать временные таблицы? И критерии, когда вы точно гарантировано требуете использовать только временные таблицы?

Не скажу конкретные критерии. Мы используем временные таблицы повсеместно, потому что мы знаем, что у нас tempdb лежит в оперативной памяти и все это работает быстро. Соответственно, я в докладе рассказал стандарты, которые мы для себя выработали за три года. В других компаниях такие стандарты, естественно, могут отличаться – это нормально. Но это то, что позволило нам за 2021 год не получить ни одного инцидента с новыми запросами, которые бы как-то замедлили базу. У нас есть легаси, мы его рефакторим, оно замедляет базу и периодически «выстреливает». Но ни один новый запрос, даже самые большие отчеты – нам не замедлили базу. Ни разу за весь 2021 год.

Сколько примерно у вас документов в самой большой таблице? Используете ли вы динамические списки в работе? И есть ли у вас с ними какие-то проблемы?

Динамические списки у нас используются крайне мало. У нас весь фронт – это либо отчеты, либо какие-то рабочие места. Динамические списки есть, но они сильно ограничиваются изначально уровнем запроса. Не пользователем, а кодом.

Хочется понять, как у вас организована работа. Сколько примерно у вас в самой большой таблице документов?

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

Пользователи могут форму списка открыть?

Теоретически – наверное, да.

Отбор могут поставить, который заставит сканировать таблицу?

Да, и это может легко положить базу. Такое бывает. Поэтому мы у нас недавно для самого большого документа программно ограничили отборы и сортировки, чтобы можно было выбрать только индексированные поля.

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

Нет, теперь там ничего этого нет, есть только стандартные индексированные поля. Это какой-то стандартный механизм – решилось в три строчки. Ничего другого мы делать не стали, потому что этими динамическими формами списка почти никто не пользуется.

*************

Данная статья написана по итогам доклада (видео), прочитанного на конференции Infostart Event 2021 Moscow Premiere.

См. также

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    5307    ivanov660    12    

56

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    9465    Evg-Lylyk    61    

44

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    5179    spyke    28    

49

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    7704    vasilev2015    20    

42

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

2 стартмани

15.02.2024    12592    250    ZAOSTG    83    

115

HighLoad оптимизация Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Принимать, хранить и анализировать показания счетчиков (метрики) в базе 1С? Почему бы нет? Но это решение быстро привело к проблемам с производительностью при попытках построить какую-то более-менее сложную аналитику. Переход на PostgresSQL только временно решил проблему, т.к. количество записей уже исчислялось десятками миллионов и что-то сложное вычислить на таких объемах за разумное время становилось все сложнее. Кое-что уже практически невозможно. А что будет с производительностью через пару лет - представить страшно. Надо что-то предпринимать! В этой статье поделюсь своим первым опытом применения СУБД Clickhouse от Яндекс. Как работает, что может, как на нее планирую (если планирую) переходить, сравнение скорости работы, оценка производительности через пару лет, пример работы из 1С. Все это приправлено текстами запросов, кодом, алгоритмами выполненных действий и преподнесено вам для ознакомления в этой статье.

1 стартмани

24.01.2024    5783    glassman    18    

40

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    14552    doom2good    49    

71
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. it-expertise 345 29.08.22 10:09 Сейчас в теме
Артем, на каком оборудовании и ПО крутится это ваше хозяйство 7-терабайтное?
2. artbear 1563 29.08.22 10:13 Сейчас в теме
Замечательный набор полезнейших чек-листов, давно ждал публикацию этого выступления!
t278; mrChOP93; sasha_r; +3 Ответить
3. Lapitskiy 1061 29.08.22 13:09 Сейчас в теме
5. Chernazem 124 29.08.22 17:08 Сейчас в теме
(3) В начале каждого блока список наших основных рекомендаций, которыми можно пользоваться как чек-листом при проверке запросов.
4. Gilev.Vyacheslav 1917 29.08.22 16:42 Сейчас в теме
с одной стороны большей частью пересказ известных методичек, ничего нового, только прочувствованный на собственном опыте, с другой стороны чем больше таких статей будет тем лучше, очередное практическое подтверждение
про шардинг уже язык устал тему подымать, бесполезно, ну хоть кто то частично таблицы различает по оперативности данных
d_sdr; mrChOP93; ivanov660; +3 Ответить
7. starik-2005 3090 29.08.22 19:13 Сейчас в теме
(4)
про шардинг уже язык устал тему подымать
Горизонтальный или вертикальный? А датаакселератор? Про него тоже никто почти не умеет, а тут он бы помог, раз железо с терабайтами памяти.
axelerleo; VVi3ard; +2 Ответить
31. пользователь 31.08.22 15:23
Сообщение было скрыто модератором.
...
33. пользователь 31.08.22 18:28
Сообщение было скрыто модератором.
...
6. ivanov660 4582 29.08.22 17:26 Сейчас в теме
1. Внесу замечание, т.к. сам недавно анализировал подобную проблему и это бросается в глаза:
В замене среза виртуальной таблицы "СрезПоследних" СостоянияСобщенийSMS на программный срез возможно автор что-то упустил, но не хватает агрегации. Без этого в виртуальной таблице "Вт_СостоянияСобщенийSMS" получим кучу лишних записей предыдущих статусов.
И да, в данном случае (при использовании временной таблицы) использоваться будет индекс, а не полное сканирование основной таблицы. Однако, на время будет влиять также количество записей помещаемых во временную таблицу и если бы не размещение temp диска в оперативной памяти, то было бы все совсем печально.

2. На мой взгляд, в некоторых случаях было бы "интереснее" сразу изменить архитектурно структуру метаданных. Иногда обновлять данные при записи в регистрах выгоднее, чем через точку брать от полей.

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

В целом мысли хорошие и правильные.
VVi3ard; RustIG; +2 Ответить
9. RustIG 1749 29.08.22 19:54 Сейчас в теме
(6)да , тема не раскрыта в части изменения метаданных конфигурации. Вопрос возник после фразы "перешли на бсп 3.1", а какой смысл был переходить при таких объёмах базы?
10. Chernazem 124 29.08.22 20:50 Сейчас в теме
(9) Про БСП - потребовалось часть нового типового функционала, и проще было обновить БСП, чем впиливать его самим. Про метаданные - тема доклада была о другом, потому про них мало. Не всегда можно влезть в метаданные, к сожалению, и приходится работать с тем, что есть.
16. TMV 14 30.08.22 10:31 Сейчас в теме
(6) так же по п.1 зацепился глаз. Но не понятно в чем именно фича - решение автора работает и так.
8. starik-2005 3090 29.08.22 19:14 Сейчас в теме
мы себе уже все самое топовое железо купили. Но оно уже не вывозит, поэтому мы смотрим в сторону оптимизации.
А мысли выделить часть в отдельный фронт не появляется? И необязательно на 1С...
11. Chernazem 124 29.08.22 20:53 Сейчас в теме
(8) Ну, сейчас всякие фронт-приложения пишутся для клиентов, и эта наша самописная база для них выступает бэком - пишем АПИ в ней универсальное. С использование Swagger. Но менеджеры привыкли, и писать для них что-то отдельное, а потом переобучать - вероятно, пока не считают целесообразно. Да и как практическое пособие по оптимизации база выступает отлично :)
12. starik-2005 3090 30.08.22 00:51 Сейчас в теме
(11)
Но менеджеры привыкли, и писать для них что-то отдельное, а потом переобучать - вероятно, пока не считают целесообразно.
Ну вот Слава топит за шаридирование. А я предлагаю часть данных выносить в датаакселератор. Есть мысли в ту сторону?
14. Gilev.Vyacheslav 1917 30.08.22 09:23 Сейчас в теме
(12) датаакселератор хорош пока хватает оперативки под 6 тб данных )))
я по пальцам могу сосчитать кто 4 Тб то озу купил

а шардированием "старый мусор" можно отложить на старый комп, и ни кто не заметит, почувствуйте разницу в требованиях к железу
18. Chernazem 124 30.08.22 12:22 Сейчас в теме
(14) Данных, кстати, на сейчас уже 9 тб :)
20. Chernazem 124 30.08.22 12:29 Сейчас в теме
(14) И львиная доля этих данных используется в оперативной аналитике для построения всяких дельт и прочих аналитических фокусов. Потому и с обрезкой/выделением на медленное железо всё сложно - бизнес хочет видеть старые данные "здесь и сейчас". У нас часть отчётов строится на реплике, но иногда лаг переноса транзакций прыгает, она не успевает и приходится переводить на рельсы прода снова. В общем пока мы ищем подходящее нам техническое решение проблем - разработчики оптимизируют код, выигрывая проценты производительности для комфортной работы пользователей :)
26. Gilev.Vyacheslav 1917 30.08.22 16:12 Сейчас в теме
(20) что вам мешает дергать с другого сервера через веб-сервисы старые данные, у нас база сервисов больше вашей,но размазав по 12 недорогим серверам все работает приемлемо - у нас 1 месяц и новая таблица в другой базе на другом диске, а иногда и сервере
для пользователя это будет все в одной базе в одном сеансе, он не видит где это лежит и как доставлено в его форму
17. Chernazem 124 30.08.22 12:22 Сейчас в теме
(12) Ну, конкретно у меня нет. С архитектором системы так же не обсуждали это.
13. PerlAmutor 155 30.08.22 06:18 Сейчас в теме
Так и не понял чем плох ТИПЗНАЧЕНИЯ(). Использую инструкцию где только можно, проблем проседания производительности не заметил, а возможностей применения гораздо больше чем у "Ссылка" и Конструктор запросов не ругается там где попадаются не ссылочные значения полей.

Еще заметил, что в одном примере оптимизации не хватает ключевого слова РАЗРЕШЕННЫЕ на всех временных таблицах, хотя по чек-листу они должны быть, ровно как индексов и тут же используется не рекомендованный В() и где-то было даже условие отрицания "НЕ чего-то там = чего-то". Вместо таких отрицаний можно как раз было бы использовать В (ЗНАЧЕНИЕ(), ЗНАЧЕНИЕ()) и тогда вероятность попадания в индекс была бы больше. Вообще не люблю конструкции типа "НЕ ПометкаУдаления = ИСТИНА", когда можно использовать "ПометкаУдаления = ЛОЖЬ", ну или "Поле <> Значение" для других значений.

Кстати недавно обнаружил проседания запроса при использовании "ПО ВЫРАЗИТЬ(Т1.Регистратор КАК Документ.ПриобретениеТоаровУслуг) = ВЫРАЗИТЬ(Т2.Регистратор КАК Документ.ПриобретениеТоваровУслуг) ". Дошло не сразу во что это разворачивается на уровне SQL.

Кстати, а что за сервер, MSSQL? Интересно посмотреть как оптимизации себя проявляют на Postgre.
15. Gilev.Vyacheslav 1917 30.08.22 10:24 Сейчас в теме
(13)
"Поле <> Значение"
это может спровоцировать скан
Chernazem; +1 Ответить
27. PerlAmutor 155 30.08.22 19:42 Сейчас в теме
(15) А конструкция "НЕ ПометкаУдаления = Истина" к скану не приведет что-ли?
34. Gilev.Vyacheslav 1917 31.08.22 18:56 Сейчас в теме
(27) тоже высока вероятность скана, но не понятен вопрос
нет смысла делать плохо вместо другого плохо, только это имел ввиду
ПометкаУдаления = ЛОЖЬ более "правильный" вариант, хотя тоже не 100%
правильный вариант - сначала сделать наиболее строгий отбор(ы) и уже в конце дофильтровать с ВАШИМ вариантом ПометкаУдаления = ЛОЖЬ (и то при условии что таких записей меньше трети в таблице, ну или не будет поводом более выгодным сканирование сделать)

для Постгреса обощенно это тоже действует, сильной разницы именно в этом аспекте не должно быть
35. PerlAmutor 155 31.08.22 18:59 Сейчас в теме
(34) Вопрос в том, чем руководствуются программисты 1С использующие в запросах условия "НЕ Поле = Значение" вместо "Поле <> Значение", если разницы все-равно не будет никакой?
44. sys1c 26.09.22 09:23 Сейчас в теме
19. smit1c 106 30.08.22 12:25 Сейчас в теме
Круто! Даже не представляю как обслуживать базу размером 6.8 терабайт.
Сколько лет в неё данные писались?....
21. Chernazem 124 30.08.22 12:31 Сейчас в теме
(19) Уже 9 тб. 5 лет примерно, но основные объемы - последние года 3, наверн.
22. Serg2000mr 691 30.08.22 12:39 Сейчас в теме
Я бы еще добавил пункт, которого почему-то нет в методичках от 1С.
Оператор
ВЫБОР КОГДА ТОГДА КОНЕЦ

- это тоже функция. Его использование в условиях запроса или соединениях приводит к скану таблиц.
23. Chernazem 124 30.08.22 12:54 Сейчас в теме
(22) Верно. Это входит в пункт про вычисляемые поля. Первый абзац блока Условия запросов. Я не стал перечислять все варианты, которые подходят под это понятие. К сожалению, все подобные моменты в полчаса доклада не уместить.
25. Serg2000mr 691 30.08.22 15:39 Сейчас в теме
(23) Это одна из самых неочевидных вещей, часто допускают ошибку здесь. И заговор молчания в интернете про это )

Про вычисляемые поля непонятно немного
Все вычисляемые поля мы предварительно рассчитываем в секции «ВЫБРАТЬ», мы не используем отборы по вычисляемым полям. Даже когда есть какие-то математические операции, мы сначала их лучше во временной таблице выберем и вычислим в секции ВЫБРАТЬ, проиндексируем, если нужно. И потом уже отберем по ним. Это работает быстрее, чем сразу вычислять в условиях, потому что при вычислении в условиях вычисление происходит для каждой строки, что крайне долго.


При заполнении временной таблицы разве вычисление не для каждой строки происходит?
28. ivanov660 4582 30.08.22 21:02 Сейчас в теме
(22) Про это написано на ИТС, вот первая ссылка сходу Эффективные условия запросов.
starik-2005; +1 Ответить
29. Serg2000mr 691 31.08.22 00:44 Сейчас в теме
(28) Из этого текста почти невозможно догадаться, что это касается не только секции ГДЕ, но и условий соединений.
24. Kontakt 109 30.08.22 15:23 Сейчас в теме
чем замеряли запросы? в рабочей базе или в тестовой. средствами 1с, sql
30. RustIG 1749 31.08.22 09:56 Сейчас в теме
(0) рлс, придуманный разрабами 1с - в итоге используете или отключили?
32. laperuz 47 31.08.22 15:54 Сейчас в теме
Добрый день. Режим RLS производительный? Интересно насколько велика разница между стандартным и производительным на таком объеме данных.
36. starik-2005 3090 31.08.22 23:17 Сейчас в теме
Сегодня приколу заради решил проверить, что быстрее:
ВЫБРАТЬ
  Регистр1.Измерение1,
  Регистр1.Ресурс1
ИЗ РегистрСведений.Мойрегистр КАК Регистр1
  ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Мойрегистр КАК Регистр2
  ПО Регистр1.Измерение1 = Регистр2.Измерение1 И Регистр1.Период < Регистр2.Период
ГДЕ Регистр2.Период  IS NULL
И
ВЫБРАТЬ
  Регистр1.Измерение1,
  Регистр1.Ресурс1
ИЗ РегистрСведений.Мойрегистр КАК Регистр1
ГДЕ
  Регистр1.Период В (ВЫБРАТЬ Максимум(Период) ИЗ РегистрСведений.Мойрегистр КАК Регистр
    ГДЕ Регистр.Измерение1 = Регистр1.Измерение1)
Кто угадает что быстрее? Во сколько раз?
37. artbear 1563 01.09.22 14:01 Сейчас в теме
(36) вариант с соединением быстрее. во много раз
38. starik-2005 3090 01.09.22 20:04 Сейчас в теме
41. Cyberhawk 135 09.09.22 08:34 Сейчас в теме
(36) В 9 из 10 случаев ставлю на то, что быстрее будет вложенный подзапрос, но вот когда стрельнет тот оставшийся один случай из десяти, то возможно сразу захочется переписать на соединение :)
Т.е. у нас на одной чаше весов - предсказуемость и стабильность, но медленно, а на другой - быстро, но с редкой значительной деградацией как самого запроса, так и потенциально всей СУБД.
42. starik-2005 3090 09.09.22 15:39 Сейчас в теме
(41) народ еще пишет ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО Период УБЫВ, но дата в индексе и это равнозначно МАКСИМУМ, только писать меньше. А в соединении есть неравенство, оно помогает уйти в скан по табличкеч при том может вытаскивать все элементы с датойя которая меньше. У меня на достаточно большой таблице левое соединение работает 25 секунд, в то время как условие с подзапросом на максимум всего 0.01 сек.
47. mikukrnet 182 01.10.24 13:18 Сейчас в теме
(42)
ть неравенство, оно помогает уйти в скан по табличкеч при том может вытаскивать все элементы с да


Оптимизатор просто понял что максимум вернет 1 значение, а условие В() нормально работает с одним или несколькими значениями
39. bulpi 217 02.09.22 02:48 Сейчас в теме
"Не рекомендуется использовать виртуальную таблицу СрезПоследних для регистров сведений, подчиненных регистратору, потому что там происходят лишние соединения с регистраторами. Особенно, если ресурсы у регистра составного типа."

???? Почему ????
Какие еще вдруг соединения, зачем ?
40. quazare 3814 09.09.22 04:48 Сейчас в теме
слишком простые запросы, чтобы быть примерами для оптимизации. нет примеров неоптимизированных запросов - "было так"

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

ну а так - для оптимизации и скорости - я бы использовал "переключатели" после конструкции ГДЕ. но тут элементарные запросы - особо не подискутируешь.
43. Hadgehogs 493 14.09.22 18:16 Сейчас в теме
Все хорошо, кроме индексов. Ну и с предвыборкой по кластерному индексу автор обманывает оптимизатор SQL, это не всегда работает.
45. axelerleo 346 28.10.22 17:22 Сейчас в теме
Если половина бед связана с RLS, не рассматривали ли вариант аналогичный тому что в Документообороте, с дескрипторами доступа?
46. Serg2000mr 691 01.11.22 19:57 Сейчас в теме
Добавлю лайфхак ускорения запросов:

Если нужно невключающее условие вхождения в период, то используем МЕЖДУ и уточняем.

Вместо:
ГДЕ Статусы.Период > &ДатаНачала И Статусы.Период < &ДатаОкончания

Правильно:
ГДЕ Статусы.Период МЕЖДУ &ДатаНачала И &ДатаОкончания И Статусы.Период <> &ДатаНачала И Период <> &ДатаОкончания
mikukrnet; +1 Ответить
48. mikukrnet 182 01.10.24 13:19 Сейчас в теме
(46) прикольно, попробуем при случае
Serg2000mr; +1 Ответить
49. pbelousov 26 20.11.24 08:07 Сейчас в теме
аж глаз задёргался опять....
про программный срез последних

"... sms1.Период < sms2.Период
где sms2.* Есть NULL"

т.е. декартово произведение всех строчек, чтобы понять, которая из них последняя,
и 99% остальных - выбросить.

чем не понравилось МАКСИМУМ(sms1.Период)
и дальнейшее соединение только с одной строкой ?
Оставьте свое сообщение