Как оптимизировать запрос получения сумм и курсов валют по счетам?

База знаний Одина — Одинэсника Форумы ODIN — Форум по 1С Предприятию Как оптимизировать запрос получения сумм и курсов валют по счетам?

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #36911
      Фото аватараOdineski
      Участник

        ВЫБРАТЬ
        СчетНаОплатуПокупателю.Ссылка КАК Ссылка,
        СУММА(СчетНаОплатуПокупателюУслуги.Сумма) КАК Сумма,
        СчетНаОплатуПокупателю.Дата КАК Дата
        ПОМЕСТИТЬ ВТ_Док
        ИЗ
        Документ.СчетНаОплатуПокупателю.Услуги КАК СчетНаОплатуПокупателюУслуги
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
        ПО СчетНаОплатуПокупателюУслуги.Ссылка = СчетНаОплатуПокупателю.Ссылка
        ГДЕ
        СчетНаОплатуПокупателю.Ссылка В(&Ссылка)

        СГРУППИРОВАТЬ ПО
        СчетНаОплатуПокупателю.Ссылка,
        СчетНаОплатуПокупателю.Дата
        ;

        ////////////////////////////////////////////////////////////////////////////////
        ВЫБРАТЬ
        ВложенныйЗапрос.Ссылка КАК Ссылка,
        ВложенныйЗапрос.Сумма КАК Сумма,
        КурсыВалют.Курс КАК Курс,
        ВложенныйЗапрос.Период КАК Период
        ИЗ
        (ВЫБРАТЬ
        МАКСИМУМ(КурсыВалют.Период) КАК Период,
        ВТ_Док.Ссылка КАК Ссылка,
        ВТ_Док.Сумма КАК Сумма
        ИЗ
        РегистрСведений.КурсыВалют КАК КурсыВалют
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Док КАК ВТ_Док
        ПО КурсыВалют.Период <= ВТ_Док.Дата

        СГРУППИРОВАТЬ ПО
        ВТ_Док.Ссылка,
        ВТ_Док.Сумма) КАК ВложенныйЗапрос
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
        ПО ВложенныйЗапрос.Период = КурсыВалют.Период
        ГДЕ
        КурсыВалют.Валюта = &Валюта оптимален ли этот запрос

      • #36912
        bot_avaOdin — Одинэсник
        Участник

          Запрос в целом решает задачу — для каждого документа из списка (&Ссылка) получает сумму услуг и дату, затем для каждой даты находит курс валюты по валюте &Валюта, ближайший к дате (максимальный период курса, не превышающий дату документа).

          Но есть несколько моментов, которые могут повлиять на производительность и читаемость:

          1. В первом запросе:
          — Используется ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетНаОплатуПокупателю с табличной частью по ссылке. Обычно табличная часть всегда связана с документом, поэтому можно заменить на ВНУТРЕННЕЕ СОЕДИНЕНИЕ — это ускорит запрос.
          — Фильтр по СчетНаОплатуПокупателю.Ссылка В(&Ссылка) — если &Ссылка большой список, убедитесь, что параметр передается корректно и индекс по ссылке есть.

          2. Во втором запросе:
          — Вложенный запрос с соединением КурсыВалют.Период <= ВТ_Док.Дата и группировкой по ВТ_Док.Ссылка, ВТ_Док.Сумма — это классический способ найти последний курс на дату.
          — Однако, если в КурсыВалют много записей, и периодов много, то соединение может быть тяжелым.
          — Можно оптимизировать, если в КурсыВалют есть индекс по Валюта и Период, и если период ограничен по диапазону.
          — Также можно рассмотреть вариант с использованием подзапроса для выбора максимального периода для каждой даты документа, чтобы избежать большого соединения.

          3. В целом, если количество документов и курсов не очень большое — запрос будет работать нормально.

          4. Если база большая, рекомендую:
          — Ограничить период выборки курсов (например, по диапазону дат документов).
          — Проверить индексы по полям КурсыВалют.Валюта и КурсыВалют.Период.
          — Рассмотреть вариант предварительного кэширования курсов в таблице значений.

          Пример оптимизации подзапроса для выбора максимального периода:

          |ВЫБРАТЬ
          | ВТ_Док.Ссылка,
          | ВТ_Док.Сумма,
          | (ВЫБРАТЬ МАКСИМУМ(КурсыВалют.Период)
          | ИЗ РегистрСведений.КурсыВалют КАК КурсыВалют
          | ГДЕ КурсыВалют.Валюта = &Валюта
          | И КурсыВалют.Период <= ВТ_Док.Дата) КАК Период
          |ИЗ
          | ВТ_Док КАК ВТ_Док

          Далее соединять с КурсыВалют по Период и Валюта.

          Итог: запрос рабочий, но для больших объемов данных стоит проверить индексы и, возможно, ограничить периоды, а также заменить ЛЕВОЕ СОЕДИНЕНИЕ на ВНУТРЕННЕЕ в первом запросе.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С