Задача с экзамена 1С Эксперт. (частично обсуждение было тут (форум Гилева))
Текст задачи:
"В базе работают 1000 пользователей. Есть регистр сведений в нем 100 млн записей. запрос select count выполняется t= 60 сек. Необходимо сделать так, чтобы данные были получены за t = 1c."
Можете ли Вы подсказать, пожалуйста, в каком направлении мыслить/искать? Преподаватель говорит, есть порядка 12 способов решить задачу.
Коллеги отвечали преподавателю (Александру Морозову) по-разному, мы заранее придумали что можно отетить и отвечали
1) требуется выполнение всех регламентных операций, дефрагментация, реиндексация
2) требуется создание некластерного индекса или сделать регистр таким, чтобы был хотя бы один некластерный индекс, т.к. scan по нему быстрее скана по кластерному индексу
Первые два совета недостаточны.
3) Пробовали ответить, что нужно хранить заведомо где-то количество в этом регистре, типо константы и при записи наборов записей или удалении - следить за тем, сколько у нас записей (жертвуем записью ради запроса по выбору количества записей) - тоже не подходит
4) Коллеги предлагали из DMV представлений или статистики получать значение - тоже преподаватель говорит нарушение лиц.соглашения, нельзя в обход rphost подключаться к SQL базе напрямую
5) может быть нужно секционирование предложить было? Но Вы писали где-то, что его оч.сложно настроить и нужны знания сертифицированного специалиста MS SQL
6) Может быть надо MDOP = 1 выставить? Т.к. если 60 секунд выполняется сканирование - может быть происходит блокировка параллельных сканов или что-то такое.
7) Мы предлагали преподавателю перестроить бизнес-логику решения. Тоже не "прокатило".
Если подскажете, что можно было бы сделать, или где почитать (направление), очень многие люди будут благодарны!
Сейчас это задание как триггер, отсеиватель, добрая часть людей отсеивается просто в самом конце экзамена:)
А они все только читают? И вообще какой уровень изоляции транзакций используется, есть уверенность? Может быть в этой задаче его нужно понизить? По логике вопроса, решение должно быть каким-то простым.
(18)Регистр периодический или нет? В него можно добавить ресурс или реквизит, в котором сохранять общее количество записей (в момент записи). Потом отбирать только последнюю запись.
Регистр периодический или нет? В него можно добавить ресурс или реквизит, в котором сохранять общее количество записей (в момент записи). Потом отбирать только последнюю запись.
Если два пользователя начнут добавлять (удалять) записи из этого регистра, то они станут в очередь на изменение
ресурса или реквизита, в котором будет храниться общее количество записей
(20)Ресурс в разных строках. Если регистр периодический, то в 8.3 если не ошибаюсь есть таблица итогов, тогда да. НО! Вам ведь нужно ускорить чтение, а это может быть куплено ценой более долгой записи. Поэтому пусть встанут. Поправьте если не прав.
"В базе работают 1000 пользователей. Есть регистр сведений в нем 100 млн записей. запрос sel ect count выполняется t= 60 сек. Необходимо сделать так, чтобы данные были получены за t = 1c."
Дедуктивный метод:
Пока пришёл к выводу, что не сделать никак! ( при учёте, что именно необходимо выполнить запрос
На форуме Гилева говорится
"разумные решения заключаются в том чтобы не сканировать таблицу в 100 миллионов строк"
Отсюда вывод что нужно сканировать частями.
На своей практики использую такой метод для быстрой очистки регистра сведений "Версии объектов" множественными фоновыми заданиями.
(4) да. надо будет попробовать сделать выборку фоновыми заданиями (с разбивкой по периодам т.е. каждое фоновое задание свой период).
(5) скорее нет т.к.
"нельзя в обход rphost подключаться к SQL базе напрямую"
Кстати сходил по ссылке в топике на форму Гилева, там писали что преподаватель требовал решить это штатными средствами платформы. Причем как я понял дополнительные константы или отдельные регистры тут создавать нельзя. Новые константы / регистры создавать не вариант, новые индексы не проходят. А что тогда вообще остается из штатных средств платформы?
(23)Как это? Прочитать в объектной технике? Вряд ли это будет быстрее, тут что-то более хитрое должно быть, в идеале нужно уйти от сканирования таблицы в 100 млн записей, но вот как? Все попытки перенести уже посчитанные данные в другой объект конфигурации экзаменатор отвергает, настройка доп. индексов тоже не подходит, прямое обращение к базе SQL минуя сервер 1С тоже нельзя.
метод РегистрСведенийМенеджер.<Имя регистра сведений>.Выбрать (InformationRegisterManager.<Имя регистра сведений>.Select)
формирует объект РегистрСведенийВыборка.<Имя регистра сведений> (InformationRegisterSelection.<Имя регистра сведений>)
в описании которого сказано
Объект этого типа возвращается методами Выбрать и ВыбратьПоРегистратору у объекта типа РегистрСведенийМенеджер. и представляет собой специализированный способ перебора записей регистра сведений.
Обход записей выполняется системой динамически. Это означает, что использование выборки не считывает все записи сразу, а выбирает их порциями из базы данных. Такой подход позволяет достаточно быстро обходить с помощью выборки большое количество записей и не загружать в память всех элементов выборки.
Знать точное количество порядка 100 млн записей - априори бред. На практике изменение логики неизбежно. Гилев верно ставит краеугольный вопрос "для чего это нужно?".
Но здесь как я понимаю чисто теоретическая плоскость решения? Фраза 12 способов меня поставила в тупик... Что же это за теоретические решения такие?
А если попытаться написать запрос так, чтобы MS SQL его распараллелил.
Программно сформировать текст запроса например для всех значений первого измерения. А потом объединить.
(36) ну на самом деле можно смастрячить регламентное задание которое будет получать это значение и сохнаять его в хранилище настроек. А пользователи будут его оттуда брать, но им потребуется права дать на получение чужих настроек
(49)Не прокатит, подобное на экзамене предлагали, преподаватель отвечал что будут примерные данные, а ему нужны точные (уж не знаю зачем). Я так понял что все формы кэширования/предварительного расчета отвергаются по этой причине.
(48)Это всё хорошо, но вот что писали на форуме Гилева:
Добрый день.
На экзамене задали такой же вопрос. Уточнения:
Сначала спросили про MSSQL в полном режиме совместимости (Read Commited Snapshot). Каждый из 1000 пользователей хочет получить точное количество записей из регистра, запрос выполняется 60 секунд. Как "средствами платформы" получить целевое время выполнения в 1 секунду?
Смущает добавление "средствами платформы". Знать бы что имели в виду, может быть какую-то реструктуризацию таблиц в конфигураторе сделать.
Пробовал еще вставить во времянку Выбрать 1 из регистра и прочитать количество через Запрос.ВыполнитьПакет() - ожидаемо медленно. Но убедиться стоило тоже.
(79) Во времена 8.0 разница была бы. В худшую сторону :)
Но сейчас же повсеместно RCSI, что при обычном чтении, что при транзакционном, что в MSSQL что в PostgreSQL...
(80) Ну это с технической точки зрения, а с точки зрения платформенной теории транзакция для других вещей. Тоже самое что цикл в одну строчку работает быстрее, чем оформленный цикл с переносами строк.
По условию, нужно найти способ, при котором получение количества записей регистра станет работать в 60 раз быстрее.
При этом:
1) база в разделенном режиме (1000 пользователей)
2) запрос 1С остается штатный
3) бизнес-логику менять нельзя
4) использования индекса недостаточно (что понятно - некоторый прирост будет, но не в 60 раз)
Я склоняюсь к тому, что речь о каких-то фокусах со стороны настроек СУБД. Причем в реальном продакшене вряд ли применимых (ибо чудес не бывает).
(78) поэтому я больше не пойду на этот дебильный экзамен. потому что вчера вечером морозов и еще 10 человек закончили битву над решением этой задачи спустя неделю, а тебе сейчас надо выдать готовый ответ.
Посмотрели у себя на базе. Регистр 1 млн записей - 40 мс.
Т.е. если было 100 млн, то было бы примерно 4 с. При это Количество(*) и выборка всех значений первого измерения одинаковы.
Сейчас к этому регистру не обращаются, т.е. блокировок не было.
Может вопрос и в блокировках при записи
Тогда уж лучше отложенные движения.
Как вариант вопрос не на знания, а на подход? Если запрос крутить, то это не подход эксперта, т.к. нужно выяснить комплексную причину.
Ну вот в MSSQL в режиме блокировочника на большой таблице в разделенном доступе в самом деле будет большая разница между SELECT COUNT(*) и SELECT COUNT(*) WITH (NOLOCK) даже в READ COMMITTED
Возможно информация поможет: попробовал в своей рабочей базе на регистре цен номенклатуры, результат в прикрепленном скриншоте, первый раз запрос отрабатывал 3 секунды, потом чаще всего меньше 0,5 секунды, но была пара "выбросов" за 1 секунду. Баз рабочая, в том числе и в этот регистр идет активная запись/чтение данных.