Доброго времени суток всем. Есть, казалось бы, незамысловатая задача:
В обработке, запросом, получаются данные из внешнего источника(вьюха). Получение данных в таблицу значений проходит, относительно, быстро.
Проблему составляет вывод этих данных пользователю. Пробовал выводить в таблицу значений на форме и в Табличный документ. Вывожу методом ЭтотОбъект.ТЗ.Загрузить(ТзРезультатЗапроса) - для таблицы значений или через построитель для табличного документа.
В среднем выгрузка 175 000 строк выводит за 2 - 3 минуты. Это чисто ЭтотОбъект.ТЗ.Загрузить(ТзРезультатЗапроса).
Собственно вопрос: Можно ли как то ускорить этот процесс?
(1) day_light, думаю никак.. думаю что даже регистр не особо поможет, потому что в ТзРезультатЗапроса уже сериализованная таблица будет.. время уходит именно на передачу с сервера на клиент и отображение данных в таблице.. регистр может помочь в случае если вы будете использовать дин. список для его отображения, а не таблицу значений
Да, можно. ОГраничить выборку отобрами вменяемым количеством данных. Ни один разумный человк стоько строк всяко физически не ссможет даже просто просмотреть, не говоря уж о редактировании.
Ни кто не сталкивался с подобными проблемами? В теории я могу вернуть результат запроса в виде xml файла, прямо из sql хранимки. Может 1с 8.3 есть какие то методы по быстрому выводу xml на экран? Это тоже бы подошло.
(7) antz, я не отрицаю что на СКД будет быстрее чем в ТЧ.. но насколько я понял товарищу данные именно в ТЧ нужны, ну или в каком то списке.. может дин. список пойдет, там еще быстрее будет чем СКД
(9) oleg21592, у него внешний источник данных подключен, там вообще танцы с бубном и выгрузкой через ТЗ не нужны, сразу в дин. списке запрос к внешнему источнику и вперед
(11) oleg21592, обычная нормальная работа дин. списка) он на любых данных так работает.. вы особо напрягаетесь когда прокручивая список документов он слегка притормаживает? у нас например это практически не заметно.. а вот в ТЧ гонять с сервера на клиент 170тыс записей и забивать оперативу на клиентском компе это да.. дерганий не будет, будет равномерное зависание при любом обновлении ))
дерганий не будет, будет равномерное зависание при любом обновлении ))
а выполнение кучи запросов к внешнему источнику имеет такую же производительность как и своей базе считаете?
если не нужен оперативно отслеживать изменения то мой выбор ТЧ.
а если нужно то выбирать только послединии скажем 100 записей, но не все в динамич списке, сам он все равно не обновится пока не подергаешь
а выполнение кучи запросов к внешнему источнику имеет такую же производительность как и своей базе считаете?
если это прямая выборка из БД, ну скажем подключаетесь вы напрямую к MSSQL, то внешние источники быстрее будут в большинстве случаев чем выборка из справочника например простым 1С - запросом, собственно просто за счет того что не будет проверяться доступ к данным как минимум. Но у человека вьюха, а не прямое чтение из таблицы, вот вьюха уже будет тормозить (я бы на его месте попробовал ее убрать и делать все необходимые соединения запросом 1С (в запросе дин. списка например и добавил бы несколько нужных таблиц в внешний источник).. хотя собственно если делать с вьюхой то тормоза от нее будут одинаковые хоть при использовании ТЧ. хоть при дин. списке, хоть в отчете СКД.
если не нужен оперативно отслеживать изменения то мой выбор ТЧ.
вам же его придется обновлять через какой то промежуток времени постоянно, что бы он обновлялся.. а это каждый раз 170к записей туда-сюда тягать ) вот если нужно скажем загрузить данные с внешнего источника, изменить их и записать обратно, либо они идут куда то в дальнейшую обработку и там все равно надо таблицу значений для параметров временных таблиц скажем в запрос, то тогда я согласен что ТЧ (ТЗ) лучше будут подходить.. но на просмотр если данные нужны то однозначно дин. список в любом раскладе.
у человека вьюха, а не прямое чтение из таблицы, вот вьюха уже будет тормозить
И с каких пор вьюхи стали однозначными тормозами? С каких пор внешние источники данных перестали работать с вьюхами? Откуда мнение, что внешние источники данных работают только с таблицами напрямую? Вы в курсе, что внешние источники данных еще и с табличными функциями могут работать? Не приходило в голову, что все эти вьюхи и табличные функции придуманы отнюдь не для замедления работы?
вы думаете вьюха будет работать быстрее чем прямой запрос с объединением по ключам (ссылкам) нескольких таблиц?)
С каких пор внешние источники данных перестали работать с вьюхами? Откуда мнение, что внешние источники данных работают только с таблицами напрямую?
можно мне конкретную цитату где я утверждал что с вьюхой работать не будет? Я утверждал что цепочка ВнешнийИсточник - вьюха - бд, будет работать медленней чем ВнешнийИсточник - БД ) причем значительно медленнее. Будете спорить с данным утверждением? С вьюхой будет работать конечно же, для внешнего источника это такая же таблица.
Вы в курсе, что внешние источники данных еще и с табличными функциями могут работать?
думаю даже больше в курсе чем вы ;) я с ними работаю регулярно
Не приходило в голову, что все эти вьюхи и табличные функции придуманы отнюдь не для замедления работы?
я прекрасно понимаю для чего они используются.. но и вы должны понимать что запрос типа sel ect top 100 * fr om ... который и будет выполняться в дин. списке будет применен к результату выполнения вьюхи (которая в свою очередь сама является запросом). Собственно та же ситуация и с наложением отбора (поиска) в дин. списке, да или просто при выборке, по сути наложении условия через where, они будут накладываться на результат отображения вьюхи
вы думаете вьюха будет работать быстрее чем прямой запрос с объединением по ключам (ссылкам) нескольких таблиц?)
Типа один и тот же запрос сам по себе и во вьюхе будет работать по-разному и точно во вьюхе тормознее?
Я утверждал что цепочка ВнешнийИсточник - вьюха - бд, будет работать медленней чем ВнешнийИсточник - БД ) причем значительно медленнее. Будете спорить с данным утверждением?
Да, я не вижу логики в данном утверждении. Похоже, у вас какое-то особенное понятие вьюхи.
(26) sssss_aaaaa_2011, вы не понимаете как работают внешние источники в 1с, и вьюхи тут не причем.. я вам открою секрет, когда вы запрашиваете данные с внешнего источника сама платформа формирует выборку данных (select) из таблицы источника (не важно что это), но и сама вьюха формирует свой запрос.. теперь пробуйте догадаться что будет, с учетом что скуль не будет склеивать два запроса (от вьюхи и от платформы 1С) в один )) собственно у меня нет времени на обучение, можете провести эксперимент если интересно.. получить данные простым чтением таблицы MSSQL и через вьюху и увидите разницу в скорости ;) если не верите на слово, ну просто сделайте да посмотрите
(27)как ни странно, но в профайлере никакой разницы пока не обнаружено. И запрос к вьюхе всегда разворачивался и разворачивается в запрос к таблицам даже при вложенных вьхах. По крайней мере на моих вьюхах. Может у вас какие-то особенные вьюхи?
РЕЗЮМЕ
Теперь, когда вы можете использовать представления, ваша способность отслеживать и обрабатывать содержание вашей базы данных, значительно расширилась. Любые вещи которые вы можете создать с запросом, вы всегда сможете определить как представление. Запросы этих представлений, фактически, запрос запроса.
(29)сударь, это не документация по продукту, а научно-популярное произведение.
В MS SQL представление(вьюха) ВСЕГДА полностью разворачивается до базовых таблиц даже при множественном вложении представлений. Учите матчать по официальным источникам.
(30) sssss_aaaaa_2011, просто сделайте эксперимент предложенный мной, замерьте время получения данных с вьюхой и без вьюхи через внешние источники. Ну может у меня какой то особенный MSSQL 2012 )) ну и на SQL.ru видимо то же какой то особенный скуль.. я вам говорю практику которая у меня вот сейчас работает, и она полностью совпадает с тем что ожидается и работает как я вам утверждаю. Чудеса..
(32) sssss_aaaaa_2011, ок, на том и разойдемся что у нас разные MS SQL..
И пока она и с sql.ru не расходится.
у вас то как раз расходится ;) на sql.ru утверждается что запрос к вьюхе это запрос запроса.. вы говорите что у вас платформенный запрос внешнего источника к вьюхе всегда преобразуется в один запрос
(33)разница в скорости у вас может возникать из-за отличий в параметрах сессий, открытых, например, SSMS и внешним источником данных 1с. У меня отличий нет и нет, соответственно, разницы в скоростях. И вьюхи разворачиваются. Что надо сделать, чтобы они не разворачивались я сходу даже не могу предположить.
на sql.ru утверждается что запрос к вьюхе это запрос запроса
Где это утвержается? В приведенной вами ссылке? Так это надпись на заборе и не более того. Еще раз - учите матчасть по официальным источникам, а не по чьим-то пересказам.
разница в скорости у вас может возникать из-за отличий в параметрах сессий, открытых, например, SSMS и внешним источником данных 1с. У меня отличий нет
у меня то же отличий нет, а разница в скорости раза в 2 чисто визуально, без замеров.. чуть освобожусь, в пятницу попробую сделать сравнительный тест с четкими цифрами
На правах идеи.
Исходную ТЗ не загружать в контекст формы, а оставлять на сервере во временном хранилище.
А на форму загружать только порцию данных исходной таблицы.
Ессно, придется реализовать механизм листания, который в серверном вызове будет синхронизировать измененные данные страницы и подгружать в форму очередную порцию данных.
Понятно, что возникает ряд проблем и неудобств. Главная - невозможность полностью прозрачно реализовать листание (как в динамическом списке). Придется для навигации специальные команды выводить.
(18) oleg21592, Ну так идея именно в том, чтобы обойтись без динамического списка, который тоже неслабый такой костыль, тянущий кучу проблем и неудобств.
Получение из хранилища, насколько я понимаю, не стоит ничего. На сервере это тупо доступ к ТЗ по ссылке.
Порционность - да, нужно реализовывать. Но мне такое решение кажется хорошей альтернативой. Лично я бы попробовал реализовать именно его. Порции можно не привязывать к количеству отображаемых строк на экране, тем более что это нормально и не сделаешь. Выбрать размер порции исходя из баланса удобство/производительность. Строк 300 на порцию, допустим. На экране просто отображать типа "порция 135 из 325". И команды для переходов. Переходы должны работать быстро. Уж точно не медленнее динамического списка.
Получение из хранилища, насколько я понимаю, не стоит ничего. На сервере это тупо доступ к ТЗ по ссылке.
а как вы ее на сервере держать собрались? насколько я понял вы предлагаете воспользоваться методом ПоместитьВоВременноеХранилище и хранить ссылку на хранилище в переменной.. но тогда я бы не стал утверждать что получение из хранилища ничего не стоит, ведь получение значений будет каждый раз вызывать сериализацию (по сути бинарный кэш (который лежит в темпах на диске на сервере, что то же не быстро) будет еще и сериализовываться что бы стать Таблицей значения на сервере, что бы можно было получить очередную порцию данных.. а вот это уже стоит какое то время) насколько оно меньшее чем перетаскивание всей ТЗ на клиента тут не знаю, это нужен эксперимент )
насколько я понял вы предлагаете воспользоваться методом ПоместитьВоВременноеХранилище и хранить ссылку на хранилище в переменной.. но тогда я бы не стал утверждать что получение из хранилища ничего не стоит, ведь получение значений будет каждый раз вызывать сериализацию (по сути бинарный кэш (который лежит в темпах на диске на сервере, что то же не быстро) будет еще и сериализовываться что бы стать Таблицей значения на сервере, что бы можно было получить очередную порцию данных.. а вот это уже стоит какое то время) насколько оно меньшее чем перетаскивание всей ТЗ на клиента тут не знаю, это нужен эксперимент )
Ну, свопится только при 20 минутах бездействия. Этим можно пренебречь. А вот насчет сериализации тонкий момент. Надо потестить.
Я надеюсь, что сериализация производится только при клиент-серверной передаче. Ведь в 8.2 можно было сохранять во временном хранилище и несериализуемые данные.
(40) AllexSoft, Спасибо, кэп. В 8.3 просто запретили сохранять во временное хранилище несериализуемые значения. А раньше можно было. Об этом есть в списке изменений. Я об этом и говорю. "Сериализуемое" <> "сериализованное". Насколько я понимаю, просто прикрыли дыру. Потому что в момент сброса кэша на диск данные придется сериализовать и несериализуемые данные потеряются. Так что я бы вовсе не отметал сходу этот вариант. Вполне нормально может взлететь. Просто самому лень проверять :)
ЗЫ. Все! Нашел подтверждение моей догадке в документации! Вот цитата с ИТС:
"Внимание! При помещении во временное хранилище фактическая сериализация значения не выполняется. Помещается ссылка на значение, которая хранится в кеше в течение 20 минут. По истечении этого периода значение сериализуется, записывается на диск (в хранилище сеансовых данных) и удаляется из кеша."
(48) herfis, хорошее замечание, не знал о таком нюансе в 8.2, почему то думал что и в 8.2 все так же было как и в 8.3 )). В свете этого в принципе да, тогда ваш вариант можно было бы попробовать, хотя бы как познавательный эксперимент.
ПС: а можно подключить обработчик ожидания и раз в минут 10 что нибудь делать с этим значением в хранилище, тогда по идее никогда в дисковый кэш не упадет
Для начала, всем огромное спасибо за развернутую тут дискуссию. Часть вариантов, предложенных тут, я уже успел опробовать. Результаты пока что не утешительны.
Далее... Относительно спора разгоревшегося между AllexSoft и sssss_aaaaa_2011 - тут все немного сложнее....
Указанная мной вьюха собирает данные из 3ех разных баз. При этом одна из баз находится на другом физическом сервере. Простое выполнение запроса вьюхи, с выходным результатом 175 000 строк, занимает около минуты. Есть много используемых повторно данных, но ввиду не возможности, на прямую, использовать в вьюхе временные таблицы, там запрос собирается из данных возвращаемых табличными функциями. От такого подхода я отказался. Не взлетит.
Отказался от динамического списка и внешнего источника - вьюхи. Просто потому что долго забирать данные из базы, которая на другом серваке.
Сейчас подумываю данные сливать в реальную таблицу в базе 1с, а от туда уже получать как угодно. То есть будет какое то время предподготовки, а потом уже формирование отчета.
Но даже с таким подходом, проблема не уйдет окончательно. Количество данных слишком велико. 175 000 - это лишь частный случай, а не предел.
В первую очередь решение будет принято на административном уровне. Заказчик будет предупрежден о длительном формировании отчета, без отборов. К слову отборов там хватает, речь в топике идет о ситуации, когда заказчик не использует их, при формировании отчета.
В данный момент я оптимизировал запрос, правда уже без вьюхи. Нужные мне данные собираются за 13 секунд. Приемлемо.
Завтра попробую урезонить заказчика и буду пробовать разные варианты вывода информации на форму. О результатах отпишусь.
Интересную тему задели. Нужно эксперимент провести будет при случае.
Возможные, но не проверенные пути:
1. Ручной вывод - на сервере через цикл выборка.следующий() собираем массив структур, возвращаем на клиент и вторым циклом выводим на форму.
2. Режим запуска без сжатия, т.к. сам процесс сжатия\расжатия при взаимодействии клиента с сервером может быть источником задержки. Актуально при работе в сети с нормальными скоростями. При медленных соединениях лучше все-таки со сжатием
Другими словами, при помещении ТЗ на сервере во временное хранилище, доступ к ТЗ через временное хранилище возможен на сервере напрямую, без всяких накладных расходов. Единократное подтормаживание должно возникнуть только после длительного (больше 20 минут) бездействия в работе с ТЗ - на восстановление ТЗ с диска в память.
С хранилищем - это интересно. Можно будет попробовать.
В данный момент реализация этой задачи выглядит следующим образом:
Хранимкой собираю данные из разных баз и делаю прямой инсерт в регистр сведений базы 1с. Скорость разнится от количества отборов, но в целом 50 000 строк попадают в регистр за 10 - 12 секунд. Нормально.
Формат регистра подогнан под выходные данные отчета. Есть ряд джойнов, высчитывание минимальных значений через джойны таблиц самих к себе. Это занимает немного времени.
Далее идет вывод информации. Тут, собственно, все стает печальнее. пробовал 3мя разными способами.
1. ТабВыбора.Загрузить(Запрос.Выполнить().Выгрузить()); - 50 000 за 1,5 - 2 минуты. Есть нюанс: оперативная память потребляемая клиентским процессом составляет 500 - 600 мб, при начальных 40. На время вывода клиент зависает намертво, не отвечая. После вывода, при попытке прокрутки в таблице значений клиент может зависнуть на долго. Пару раз не дождался.
2. Динамический список с произвольным запросом. Первую порцию записей выводит почти мгновенно. Оперативки не жрет, но прокрутка невозможно лагает. Пока что не уверен, что этот вариант подходит. Прокрутить оперативно на несколько страниц не реально - подвисает.
3. Вывод отчетом на СКД. В отличии от первого варианта, выполнение отчета можно отменить в любой момент безболезненно. В процессе вывода, можно спокойно выполнять любые действия в пользовательском интерфейсе. Не знаю как там проведение документов, не проверял, но переходы по формам списков и открытие форм объектов отлично проходят. Оперативы не жрет вообще. Не понимаю как СКД выводит данные, но не потребляет практически ни мегабайта, сверх того что уже занято процессом. Казалось бы - это оно. Если бы не скорость вывода. Все то же количество информации выводится за 5 минут! по минуте на 10 000 записей. Как вы понимаете - это долго.
Собственно вопрос остается открытым. Сейчас все упростилось. Взять данные из регистра - вывести на форму. Как это сделать оперативно? Не уж то управляемые формы не предназначены для подобного? Я понимаю объемы данных бессмысленно велики. Я знаю что пользователю оно не надо. Этот вопрос сейчас решается. Но все же. Как думает сообщество каков правильный подход к этой, казалось бы тривиальной, задаче?
(53) Индексы на всех ключевых полях, по которых джойны происходят, стоят. Но мне кажется что с индексами там все нормально. В варианте где происходит выгрузка данных на форму, получение данных проходит быстро. Долго проходит их выгрузка на форму.
(52) day_light, СКД с нужным отбором. Хочет выдеть 175к строк, чтобы потешить самолюбие? Пусть ждет 5 минут. Хочет видеть нужную информацию, пусть ставит отбор и видит в тот же момент.
(52) day_light, Отчет СКД в тонком клиенте по дефолту исполняется фоновым заданием на сервере. Поэтому интерфейс и не лочится. На клиента передается готовый табличный документ по готовности.
С самого начала было очевидно, что узким местом является большой размер клиентского контекста. Поэтому странно пытаться оптимизировать скорость получения выборки на сервере. Что-то выиграть можно, только смысл, если батлнек в другом месте.
(52) day_light, а типы данных у вас там какие используются в регистре?
ПС: динамический список это тот же СКД вид сбоку.. ничего оптимальнее не придумаете.. ТЗ будет тормозить из за большого расхода оперативы, отчет на СКД будет тормозить потому что сразу выгребает все данные.. а дин. список это как раз что то среднее, выбирает небольшими порциями, средствами СКД, но выводит в список формы..
(60) Типы данных - внешние источники данных, и числа(15,3). Внешние источники - ссылки, строка(9).
Сейчас, наконец то, закрыли организационные вопросы. Внесли в обязательный регламент один из ключевых отборов. Теперь, по идее, количество строк в отчете, не должно превышать 10 000. Варианты с выходными данными, без отборов, оставлю в виде выгрузки в какой то *.csv файл, без вывода на экран. Пусть потом заказчик хоть что с ними сделает.
Для себя выбираю вариант с формированием через СКД. И вариант с группировками сменить можно будет без проблемно и проблем с клиентским процессом нет, во время работы.
Тему пока не закрываю, потом отпишусь, по факту сдачи задачи.
Всем спасибо за содействие.
п 2. - Динамический список с произвольным запросом, зависит, конечно, от конкретной задачи, но для своего случая считаю что это бяка. Собственно сражение с ним к первому варианту (ТабВыбора.Загрузить(Запрос.Выполнить().Выгрузить()) меня и привело. В отличии от второго, работоспособность его оказалась не чисто теориической, но и практической. Проще подождать 10 сек. пока обновляется таблица формы, чем постоянно ждать при пролистывании. Помимо прочего задержки означают то, что такой список постоянно долбит базу запросами, формат которых на уровне СУБД доподлинно не известен. Даже выцепив его, изменить врят ли что-то получится, т.к. то, что сформировано платформой нам подвластно лишь косвенно.
п 3. - СКД штука местами загадочная, посему стараюсь вне отчетов ее не прикручивать. Надеюсь в табличный документ выводите, а не таблицу формы?
Однако же, если у Вас появился регистр сведений, почему к нему не приделать простой динамический список (см. Форму списка регистра)
(54) Infector, Ничего загадочного в СКД нет. "Магия" в программировании существует только в белых пятнах знаний.
Вне отчетов СКД прекрасно используется. Только ручной работы в сравнении с отчетами заметно больше, т.к. как раз в отчетах СКД используется много "магии" (платформенного "сахара") для облегчения создания простой отчетности.
(59) herfis, У меня подозрительное отношение к СКД началось с некоторых печатных форм из ЗУП, вернее их быстродействия. Особенно порадовал когда-то "табель". Допускаю, что не сама СКД виновата, а сверхтяжелый запрос, который в нее заложили, но осадок остался, когда узкое место было перестроено без применения СКД. С тех пор СКД - там, где нужно дать возможность пользователю настроить то, что он хочет (группировки, отборы и т.д.). В остальных случаях - обычный запрос видится более предсказуемым.
(59) herfis, кстати. Заметил единожды одну очень интересную вещь, связанную с отчетом на СКД. Может ты сталкивался.
Сформировал отчет.
Клиентский процесс не забрал оперативной памяти.
Поменял в отчете настройки. При этом выходная форма отчета стает полупрозрачной, и на ней появляется надпись "Отчет не сформирован", хотя на фоне видны прежде выведенные данные.
Отчет не формирую.
Жму несколько раз PageDown, для прокрутки в низ. Все зависает и клиентский процесс начинает бешено жрать память. Стабильно с приростом по 5-10 мб/с.
Доходит до 300мб. и 1ска вылетает. Без ошибок. Просто процесс закрывается.
И еще один вопрос, в этой же теме.
Как я и говорил отчет на СКД формируется не блокируя интерфейс пользователя, что очень удобно. Но это при штатном вызоке кнопки "Сформировать". Когда же вызываю ЭтотОбъект.СкомпоноватьРезультат(), в форме. Отчет виснет и ждет выполнения. Можно как то формировать отчет на скд, без блокирования пользовательского интерфейса?