Почему запрос может работать неоптимально:
1. в виртуальных таблицах не используются параметры
2. соединения с подзапросами, условия с подзапросами, вложенные подзапросы
3. соединения с виртуальными таблицами
4. наложение условий на неиндексированные поля
5. получение данных из составного типа через точку
6. использование вложенных подзапросов (с большой вложенностью)
Подробнее: 1. В виртуальных таблицах не используются параметры Рекомендация
Надо использовать по-максимуму параметры виртуальных таблиц (Остатки, Обороты, ОстаткиИОбороты) Объяснение
Сперва выбираются данные для виртуальных таблиц, а потом уже на них накладываются условия, соединения и т.д. Т.е. если сделать запрос:
То сперва выберется вся имеющаяся номенклатура со всеми остатками, а потом на неё наложится условие склада. Надо так:
2. Соединения с подзапросами, условия с подзапросами, вложенные подзапросы Рекомендация
Надо вообще стараться не использовать подзапросы, а переписать их во временные таблицы. Соединять следует только объекты метаданных или временные таблицы. Объяснение
Оптимизатор СУБД часто не может составить оптимальный план выполнения таких запросов. Проблема в определении алгоритма соединения, который зависит от количества записей в выборке. При использовании временных таблиц размер выбираемых таблиц известен заранее, поэтому СУБД легче составить оптимальный план выполнения. Но при этом появляются накладные расходы на создание временных таблиц.
3. Соединения с виртуальными таблицами Рекомендация
Перед соединениями с виртуальными таблицами их следует предварительно выбрать во временные и соединять уже с ними. Объяснение
Виртуальные таблицы часто содержатся в нескольких физических таблицах СУБД, в итоге для их выборки составляется подзапрос, а проблемы с ним расшифрованы в п.2.
4. Наложение условий на неидексированные поля Рекомендация
Для условий запросов должны существовать подходящие индексы.
При соединении с виртуальными таблицами, их необходимо проиндексировать по полям, участвующим в соединении. Объяснение
При отсутствии подходящего индекса СУБД будет сканировать всю таблицу для соединения по каждому полю.
5. Получение данных из составного типа через точку Рекомендация
В запросах использовать ВЫРАЗИТЬ(... КАК ...), в описании типов полей указывать только необходимые типы. Объяснение
При выполнении запроса для составного типа без ВЫРАЗИТЬ будет происходить соединение с таблицами всех объектов, входящих в составной тип.
Данная задача может быть решена как с использованием вложенных запросов, так и с помощью. временных таблиц. Попробуем решить задачу, используя временные таблицы. Сначала приведем весь текст запроса, а потом кратко разберем по частям принцип его работы.
Текст запроса:
Данный пакетный запрос содержит три подзапроса. Рассмотрим их подробнее.
Первый запрос пакета группирует данные по периоду, контрагенту и номенклатуре и помещает их во временную таблицу втБезЦены. Далее мы будем соединять эту таблицу с таблицей цен номенклатуры и получим небольшой выигрыш в том, что соединять будем уже сгруппированные данные.
Во втором подзапросе мы соединяем временную таблицу с регистром сведений «ЦеныНоменклатуры» при этом из регистра сведений мы выбираем МАКСИМАЛЬНУЮ дату из меньших или равных дат. Результат этого подзапроса также помещаем во временную таблицу (втМаксПериод). Посмотрим, какие данные попадают в эту таблицу:
Рис. 8 Временная таблица втМаксПериод
В последнем запросе пакета, мы еще раз соединяем временную таблицу с таблицей цен номенклатуры. На этот мы соединяем таблице по номенклатуре и периоду.
Если Вы работаете с одной таблицей, то Вам нет необходимости использовать объединение. Совсем другое дело, когда Вы работаете с несколькими таблицами и Вам, например, нужно получить данные, и по покупкам и по продажам товаров.
Для объединения используется предложение ОБЪЕДИНИТЬ. На самом деле происходит объединение результатов запросов, то есть каждый запрос собирает данные независимо друг от друга, а затем эти результаты объединяются в один. И только над последним запросом выполняются остальные операции, например, упорядочивание и расчет итогов.
При объединении запросов происходит "вертикальное склеивание" результатов, то есть сначала идут строки результата первого запроса, затем второго.
Перейдём к практике:
Результат этого запроса следующий:
Номенклатура Количество Сумма
Бумага А4 25 14 500
Стикеры 500л 8 4 880
Файл прозрачный 5 4 100
Набор офисный 8 8 840
В итоге мы получим две таблицы, которые будут соединены друг с другом. Трудно увидеть, где кончается документ Приходная и начинается документ Расходная. Но мы сделаем кое-что, чтобы понять это:
Как видно из текста запроса мы задали для каждого документа разные псевдонимы для количества и суммы. Также на место тех полей, где мы будем получать значения суммы и количества, поставим нули. Это нужно, чтобы пустые значения количества и суммы заменялись нулями.
Номенклатура КолПриход СумПриход КолРасход СумРасход
Бумага А4 25 14 500
Стикеры 500л 8 4 880
Файл прозрачный 5 4 100
Набор офисный 8 8 840
Набор офисный 1 1 105
Файл прозрачный 1 820
Стикеры 500л 1 610
Теперь нам нужно из результат запроса убрать дублирующиеся элементы. У нас два запроса и если мы будем сворачивать, каждый отдельно, чтобы исключить дублирующиеся элементы, то у нас ничего не получится. Поэтому мы приведём запрос к следующему виду:
Итак, мы видим, что весь наш запрос заключён в скобки и назван как ВложенныйЗапрос. Это сделано для того, чтобы мы смогли сгруппировать записи из обоих подзапросов и исключить дублирующиеся элементы. Такая конструкция называется вложенным запросом. Результат этого запроса следующий:
Номенклатура КолПриход СумПриход КолРасход СумРасход
Бумага А4 25 14 500
Стикеры 500л 8 4 880 1 610
Набор офисный 5 4 100 1 1 105
Файл прозрачный 8 8 840 1 820
В итоге получаем сгруппированную таблицу, в которой данные из вложенных подзапросов приведены к понятному виду. Количество вложенных запросов не должно превышать 255. Мы использовали здесь четыре подзапроса.
Если мы хотим оставлять в запросе только уникальные значения записей при этом, не используя группировку. Нужно писать предложение ОБЪЕДЕНИТЬ без ключевого слова ВСЕ.