Курс по Оптимизации 1С – Занятие №7
В рамках этого занятия необходимо изучить следующие материалы.
Модуль 3. Причины медленной работы
- Глава 8. Анализ причин медленной работы и оптимизация системы
- Подзапрос в условии соединения
- Работа с полями состовного типа в запросах
- Параметры виртуальной таблицы. Запросы в цикле
- Особенности работы с виртуальными таблицами
- Рекомендации по написанию запросов
Практическое задание
К сожалению, у Вас недостаточно прав для дальнейшего просмотра.
Если Вы приобрели курс, но еще не активировали токен — пожалуйста, активируйте доступ по инструкциям, высланным на Ваш email после покупки.
Если Вы не залогинены на сайте — залогиньтесь, вернитесь на эту страницу и обновите ее.
Если Вы залогинены, у Вас активирован токен доступа, но Вы все равно видите эту запись — напишите нам на e-mail поддержки.
Комментарии / обсуждение (221):
Комментарии закрыты
Добрый день.
Решив все практические задания решил опробовать новые знания на рабочей базе.
В базе есть рег. сведений “ЦеныНоменклатуры”. Все измерения НЕ составные, ссылочные и ведущие. Записей в регистре 9,2 млн.
Измерения в порядке их следования: ТипЦен, Номенклатура, КодТовара (справочник, который по сути обозначает номер товара в партии), Характеристики (не используются).
Никак не удается попасть в индекс при получении среза последних, хотя известны все значения (ТипЦен, Номенклатура, КодТовара).
Пробовал следующие варианты:
– передавал параметры в виртуальную таблицу отдельно для каждого измерения
– собирал все данные в одну таблицу и передавал в параметры в виде структуры “(ТипЦен,Номенклатура,КодТовара) В (ВЫБРАТЬ…)” – эта конструкция работает гораздо медленнее чем предыдущий вариант
Сейчас остановился на таком варианте:
– собрал все данные в одну таблицу и соединил ее с физической таблицей с последующей обработкой – выполняется за доли секунды.
Столкнулся с такой же проблемой в регистре накопления – получаю остатки заполнив все параметры, но плане запросе явно видно что в индекс не попадает полностью (SEEK… WHERE…).
В этом случае не получится использовать физическую таблицу…
Как попасть в индекс? Что я делаю не так?
…
(текст комментария доступен только участникам Мастер-группы)
Спасибо за информацию.
Да, используем 8.3, но включить итоги для регистра сведений не можем, т.к. в некоторых запросах из среза получают еще и номер строки, а это поле исчезает если включить итоги по регистру сведений.
…
(текст комментария доступен только участникам Мастер-группы)
Здравствуйте. У меня получился запрос, по которому оптимизатор выбрал Nested loops, в плане запроса видно, что оператор с первой таблицей вернул 0 строк, оператор со второй таблицей не выполнялся ни разу, тем не менее второй оператор имеет стоимость почти в половину всего запроса. Как это объяснить?
…
(текст комментария доступен только участникам Мастер-группы)
Здравствуйте, помогите пожалуйста понять почему запрос 2 отрабатывает практически в два раза быстрее.
…
(текст комментария доступен только участникам Мастер-группы)
Андрей, а зачем организацию добавлять во временную таблицу? Она же передается параметром виртуальной.
Посмотрел планы запросов, они практически идентичны только в одном случаи поиск с отбором по параметру, а во втором с отбором по #tt3._..RRef
Протестировал запрос ~700 раз +- одинаково.
И еще вопрос по моим запросом, в планах запросов есть параметр TotalSubtreeCost, как вы говорили он измеряется в “попугаях” а почему в двух планах он очень разный, причем в более быстром запросе он намного больше? параметр TotalSubtreeCost зависит от EstimateRows?
…
(текст комментария доступен только участникам Мастер-группы)
Добрый день. Подскажите, что в sql-ном тексте запроса значит оператор WITH(NOLOCK)?
…
(текст комментария доступен только участникам Мастер-группы)
Добрый день. Можно посмотреть исходный запрос для задания 8.5? Задание 8 уже решил.
…
(текст комментария доступен только участникам Мастер-группы)
Задание 8-5. Не является опечаткой то, что дважды выбирается поле T12._Description? Может быть должно быть T11._Description?
…
(текст комментария доступен только участникам Мастер-группы)
Здравствуйте. Возник вопрос по заданию 07.
Является ли нормальной практикой использовать подзапрос в параметрах виртуальной таблицы остатков (Измерение1, Измерение2) В (ВЫБРАТЬ …). Разве в этом случае не будет соединение виртуальной таблицы с подзапросом?
…
(текст комментария доступен только участникам Мастер-группы)
Здравствуйте,
Виртуальную таблицу соединять с физической таблицей – это неоптимальный запрос, А вот виртуальную таблицу с временной таблицей соединять можно? Или лучше делать две временные таблицы, а потом их соединять?
…
(текст комментария доступен только участникам Мастер-группы)
В задании 8.1 в запросе есть строка | ОстаткиНоменклатурыОстатки.СтрокаЗаказа.ДокументВладелец КАК Заказ.
Что-то я не пойму какого типа может быть СтрокаЗаказа?. По идее строка заказа -должно содержать примитивный тип с указанием на номер строки ТЧ документа, но в таком случае невозможно обращение через точку к реквизиту ДокументВладелец. Следовательно СтрокаЗаказа это поле ссылочного типа. Неужели имеется в виду справочник с номерами строк, имеющим реквизит ДокументВладелец?
…
(текст комментария доступен только участникам Мастер-группы)
Я выполнил 2 запроса в системе:
1) ВЫБРАТЬ ПЕРВЫЕ 1
РС_Тест1.СоставнойТип
ИЗ
РегистрСведений.РС_Тест1 КАК РС_Тест1
УПОРЯДОЧИТЬ ПО
СоставнойТип
2) ВЫБРАТЬ
МИНИМУМ(РС_Тест1.СоставнойТип) КАК СоставнойТип
ИЗ
РегистрСведений.РС_Тест1 КАК РС_Тест1
В итоге показатель TotalSubtreeCost для первого запроса оказался равен аж 8,5 единицам, в то время как для второго всего 0,95 единицы. Визуально, действительно, первый запрос выполняется дольше.
Хотя в видеоуроке было сказано обратное.
В чем интересно тут может быть дело?
База – та самая, на которой проводится обучение.
…
(текст комментария доступен только участникам Мастер-группы)
Андрей добрый день!
Есть ли рекомендации по использованию индекса во временной таблице?
Ты говорил, что далеко не всегда он будет использован, и зачастую системе легче использовать скан таблицы чем ее индекса.
А что в случае, если в запросе к ней происходит несколько обращений, как например в Домашнем задании 07, где по ней можно и фильтровать и Таблицу остатков, и таблицу лимитов?
…
(текст комментария доступен только участникам Мастер-группы)
Подскажите, пожалуйста, что означает ? в тексте sql запроса, например тут:
ON ((T4._Fld5616RRef = T5._Reference124_IDRRef) AND (? = T5._Fld2712RRef))
…
(текст комментария доступен только участникам Мастер-группы)
Это как-то зависит от версии платформы или SQL Server? Потому что у меня в профайлере параметры обозначаются как @P1, например.
…
(текст комментария доступен только участникам Мастер-группы)
Добрый день!
1. Где я могу взять базу для решения ДЗ?;
2. Хочу получать уведомления на ответ текущего комментария.
Добрый день, Рамиль!
<1. Где я могу взять базу для решения ДЗ?;
База для выполнения большинства ДЗ не нужна, для выполнения ДЗ достаточно скринов и текстов запросов которые к ДЗ прилагаются.
<2. Хочу получать уведомления на ответ текущего комментария.
Такой функции на данный момент на сайте нет. Но мы работаем над улучшением сайта.
Добрый день.
В ходе просмотра видео про поля составного типа решил провести следующий эксперимент – написал запрос (см. прикрепленный файл ТекстЗапроса.txt);
Запрос по формированию временной таблицы приведу в тексте сообщения:
exec sp_executesql N’INSERT INTO #tt1 (_Q_001_F_000TRef, _Q_001_F_000RRef) SELECT TOP 10
T1._RecorderTRef,
T1._RecorderRRef
FROM _AccumRg18 T1 WITH(NOLOCK)
WHERE (T1._RecorderTRef = @P1)’,N’@P1 varbinary(4)’,0x0000000C
Я правильно понял что в такой запрос в СУБД формирует таблицу с двумя колонками? следующего вида:
RecorderTRef RecorderRRef
Документ.Продажа Ссылка1
Документ.Продажа Ссылка2
…
Документ.Продажа Ссылка10
Смущает ситуация из скриншота (см. прикрепленный файл Скриншот.jpg) и текст запроса в терминах СУБД по временной таблице (см. прикрепленный файл ТекстЗапроса.txt) – и как следствие возникает вопрос:
Хотя на скриншоте в конструкторе запроса видно что поле Регистратор осталось составным, но ведь во временную таблицу попали только регистраторы имеющие тип Документ.Продажа – каким образом получаются левые соединения с таблицами других документов?
Вот файлы-вложения из моего сообщения выше.
…
(текст комментария доступен только участникам Мастер-группы)
Значит дело в платформе, а я думал что оптимизатор СУБД окажется умнее.
Я специально не использовал ВЫРАЗИТЬ при создании временной таблицы – расчет был следующий:
1) когда в видео 2 модуля вы рассказывали про статистику, то говорилось что например если есть в таблице колонка “номенклатура” то статистика содержит информацию сколько и каких номенклатур содержится в этом столбце.
2) в каком то видео говорилось что когда создается временная таблица то по ней формируется статистика.
3) Поскольку благодаря статистике известно что есть только Документ.Продажа оптимизатор догадается, что нужно соединиться только с его таблицей.
…
(текст комментария доступен только участникам Мастер-группы)
…
(текст комментария доступен только участникам Мастер-группы)
Задание 8-2
Нет выбора полей из первой таблицы внутреннего соединения “ТаблицаНоменклатуры”. В качестве оптимизации можно поместить «ТаблицаНоменклатуры» во временную таблицу и в параметрах виртуальной таблицы СрезПервых добавить условие на Номенклатуру и Характеристику из этой временной таблицы.
Я посмотрела, что такое решение предлагают и другие участники. Я правильно понимаю, что это решение будет оптимальнее, так как поиск будет работать быстрее, чем соединение (для данного примера)?
…
(текст комментария доступен только участникам Мастер-группы)
Задание 7. В решении в параметрах виртуальной таблицы идет условие (Склад = &Склад и Номенклатура в (Выбрать ВремТабл.Номенклатура….), а если во ВремТабл добавить колонку “Склад” со значением &Склад и уже в параметрах виртуальной таблицы использовать конструкцию (Склад, Номенклатура) В (Выбрать ВремТабл.Склад, ВремТабл.Номенклатура). Может быть такое решение оптимальнее?
…
(текст комментария доступен только участникам Мастер-группы)
А объясните почему так более оптимально?
…
(текст комментария доступен только участникам Мастер-группы)
Андрей, появился еще вопрос по полям составного типа.
Справедливо ли, что следует использовать для составного типа ВЫРАЗИТЬ() везде, где ясно какой тип нужен? В нижеприведенном запросе, при формировании временной таблицы, нужно принудительно указывать тип? Считаем что поле ДокументОснование имеет тип нескольких разных документов.
ВЫБРАТЬ Выразить(Операция.ДокументОснование как Документ.Отгрузка) как Отгрузка
ПОМЕСТИТЬ ВТ_Отгрузки
ИЗ
……
;
////
ВЫБРАТЬ Ссылка из Документ.Отгрузка ГДЕ ССЫЛКА В (Выбрать Отгрузка ИЗ ВТ_Отгрузки)
…
(текст комментария доступен только участникам Мастер-группы)
И еще есть вопрос по решению практического задания номер 7:
1)Почему Вы сначала получили ВТ ВремТаблицаНоменклатураИОстаток на основе соединения Товаров и Остатков, а уже потом соединили ее с таблицей лимитов в отдельном подзапросе, единый запрос с соединением 3х таблиц сразу не оптимален?
2) у Вас в результирующем запросе применяется условие:
ГДЕ ВремТаблицаНоменклатураИОстаток.КоличествоОстаток – ВремТаблицаНоменклатураИОстаток.Количество < Лимиты.Лимит
не помню в каком именно видео, но Вы указывали, что такое условие, т.е. когда в одной из части условия находится вычисляемое выражение, может привести к сканированию или я не верно понял рекомендацию? Я именно по этому решил сначала во вложенном запросе рассчитать это поле "КоличествоОстаток – Количество", а уже "на верху" сравнить с лимитом, в данном случае это излишне?
…
(текст комментария доступен только участникам Мастер-группы)
Так же еще интересно, чем конструкция “Left Outer Join” и “Left Semi join” различаются и в каких случаях применяется та и другая в соединениях?
…
(текст комментария доступен только участникам Мастер-группы)
А какая конструкция в запросе 1С позволяет оптимизатору использовать Left Semi join? Просто увидел данную конструкцию в Nested Loops в одном из планов запросов в заданиях, а запроса 1С там не было приложено.
Так же, если не сложно, интересно слово OPTIMIZED в Nested Loops.
…
(текст комментария доступен только участникам Мастер-группы)
Спасибо большое
А не подскажите конкретные ресурсы или книгу, где можно справляться об операторах с возможным синтаксисом? Может есть какие-то, которые вы порекомендовали бы, чтобы не сканировать постоянно гугл.
…
(текст комментария доступен только участникам Мастер-группы)
Добрый день, Андрей.
Появилось несколько вопросов:
1) если у нас соединяются левым соединением две виртуальные таблицы Т1 и Т2, имеющие схожие структуры, например: Товар, склад, Характеристика, Количество и мы знаем массив номенклатуры и склад выборки, вопрос: Наложив условия на левую виртуальную таблицу (в ее параметрах), необходимо ли на накладывать условия и на правую таблицу, если соединение будет идти по тем же полям или достаточно соединения по полям Товар и Склад? Оптимизатор самостоятельно не наложит ли эти условия на правую таблицу?
2) индекс ТЧ документа состоит из ссылки на документ и некоего KeyField, судя по всему это не номер строки, т.к. у него другое имя, что представляет из себя это поле, просто еще один уникальный код?
3) не могу понять до конца условие, которое накладывает оптимизатор на таблицу итогов:
WHERE:(([Abramenko_Plazma_Test].[dbo].[_AccumRgT22].[_Fld21] as [T4].[_Fld21]CONVERT_IMPLICIT(numeric(16,0),[@P3],0))
AND
([Abramenko_Plazma_Test].[dbo].[_AccumRgT22].[_Fld21] as [T4].[_Fld21]CONVERT_IMPLICIT(numeric(16,0),[@P4],0))
понятно, что тут он выбирает не нулевые остатки в таблице, но зачем он добавляет вторую конструкцию (после AND), ведь она идентична первой, на мой взгляд или я ошибаюсь?
почему-то по вопросу 3 режется условие при добавлении комментария…размещу текст в текстовом файле
написал
…
(текст комментария доступен только участникам Мастер-группы)
Пример: таблицы имеют одинаковую структуру “Склад,Товар,Количество” запрос получает данные по массиву номенклатуры и по одному складу. Если не использовать ВТ, а написать все в одном соединении:
ВЫБРАТЬ
ОстаткиТоваровОстатки.Товар,
ОстаткиТоваровОстатки.ОстатокНаСкладе,
ОстаткиРезервовОстатки.КоличествоОстаток КАК ОстатокВРезерве
ИЗ РегистрНакопления.ОстаткиТоваров.Остатки(,Склад = &СкладИ Товар В (&СписокТоваров)) КАК ОстаткиТоваровОстатки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиРезервов.Остатки КАК ОстаткиРезервовОстатки
ПО ОстаткиТоваровОстатки.Склад = ОстаткиРезервовОстатки.Склад
И ОстаткиТоваровОстатки.Товар = ОстаткиРезервовОстатки.Товар
Обязательно ли накладывать условие “Склад = &СкладИ Товар В (&СписокТоваров)” в параметры второй виртуальной таблицы ОстаткиРезервовОстатки, если соединение у нас ЛЕВОЕ и идет по тем же полям или можно написать, как в примере, т.е. оставить ее без параметров?
…
(текст комментария доступен только участникам Мастер-группы)
Андрей, в одном из уроков вы сказали, что в платформа 8.3 изменился подход к работе с временными таблицами. А можете рассказать подробнее?
…
(текст комментария доступен только участникам Мастер-группы)
Понял, спасибо!
Убежден что в 8-5 идет соединение с виртуальной таблицей оборотов РН а не просто с подзапросом. Причем, соединение производится по полю регистратора. По крайней мере у себя воспроизвел нечто подобное.
…
(текст комментария доступен только участникам Мастер-группы)
Ошибся уроком, не там написал. В видео уроке “79 Анализ неоптимальных запросов” при включении анализа запросов в ЦУП вы несколько раз говорить, что будет серьезная нагрузка на систему при включении анализа, поэтому его нужно выполнять короткое время и прочее. А вот при включенном анализе запросов сервисом Гилева таких слов не звучит. В чем принципиальное различие механизмов если один очень грузит систему, а другой нет? Оба же ТЖ анализируют.
…
(текст комментария доступен только участникам Мастер-группы)
В уроке “67. Другие причины медленной работы запрос. Нулевые строки.” При выборе остатков из регистра накопления используется оператор Stream aggregate его назначение ясно и почему он выбрался тоже. Но вот при повторении у себя на компьютере примера из урока у меня вместо Stream aggregate был использован опетор Hash Match. Почему? И как в данном случае работает этот оператор, т.к. я думал, что нужен для соединения таблиц, а не для группировки строк?
…
(текст комментария доступен только участникам Мастер-группы)
Здравствуйте. Я только сейчас обратил внимание на один момент.
Если сделать запрос:
“ВЫБРАТЬ ПЕРВЫЕ 10
ПродажаТабличнаяЧасть.Ссылка,
ПродажаТабличнаяЧасть.Товар
Из
Документ.Продажа.ТабличнаяЧасть Как ПродажаТабличнаяЧасть”
То выводятся представления документа продажа и справочника товары, но при этом SQL profiler показывет запрос из одной таблицы табличной части документа. Далее если смотрим содержимое этой таблицы то там только ссылки на документ и товар, т.е. ни какого представления, которое можно было бы вывести в консоль. Как так? От куда появляется представление?
…
(текст комментария доступен только участникам Мастер-группы)
Я несколько раз внимательно просмотрел трассировку, но запросов на получение представления после основного так и не увидел. А может быть, что так какие-то другие события должны быть настроены в SQL Profiler?
…
(текст комментария доступен только участникам Мастер-группы)
Я нашел эти запросы, но заметил другую закономерность. Когда выполняешь запрос в консоли первый раз они появляются, если выполнить повторно то их уже нет в трассировке. Где сохраняются значения представлений в промежутке выполнения, если не видно чтения из кэша?
…
(текст комментария доступен только участникам Мастер-группы)
Возник вопрос по ходу решения: а как на сервере СУБД будет выглядеть работа с табличной частью объекта как таблицей значений? Например, ТабличнаяЧасть.Выгрузить().Свернуть(“Товар”, “Количество”) прямо в модуле документа-объекта?
…
(текст комментария доступен только участникам Мастер-группы)