×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

2.11.3. Управление планировщиком с помощью явных JOIN Предложения запроса

Существует возможность в некоторой степени управлять планировщиком запросов, используя явный JOIN синтаксис. Чтобы понять значимость этого аспекта, необходимо рассмотреть базовые сведения.

В простом запросе с соединением, например:

SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;

планировщик может соединять указанные таблицы в произвольном порядке. Например, он может сформировать план выполнения запроса, в котором A соединяется с B по WHERE условию a.id = b.id, а затем присоединяет C к полученному результату, используя другое WHERE условие. Или же можно выполнить соединение B с C, а затем соединить A с полученным результатом. Либо можно соединить A с C, а затем объединить их с B — но это было бы неэффективно, так как пришлось бы сформировать полное декартово произведение A и C, поскольку в WHERE предложении ON отсутствует подходящее условие для оптимизации соединения. (Все соединения в Digital Q.DataBase процессе выполнения происходят между двумя входными таблицами, поэтому необходимо формировать результат тем или иным способом.) Важно то, что эти различные варианты соединения дают семантически эквивалентные результаты, но могут иметь колоссально разную стоимость выполнения. Следовательно, планировщик изучит их все, чтобы попытаться найти наиболее эффективный план выполнения запроса.

Когда запрос затрагивает только две или три таблицы, существует не так много вариантов порядка соединения, о которых стоит беспокоиться. Но количество возможных порядков соединения растет экспоненциально по мере увеличения числа таблиц. Если количество входных таблиц превышает десять, проведение исчерпывающего поиска всех возможных вариантов становится нецелесообразным, при этом даже для шести или семи таблиц процесс планирования может занять чрезмерно много времени. При избыточном количестве входных таблиц Digital Q.DataBase планировщик переключается с исчерпывающего поиска на генетический вероятностный поиск по ограниченному числу вариантов. (Порог переключения задается с помощью соответствующего geqo_threshold параметра времени выполнения.) Генетический поиск требует меньше времени, однако он не гарантирует нахождение оптимального плана выполнения запроса.

Если запрос содержит внешние соединения, планировщик имеет меньше степеней свободы, чем при обработке обычных (внутренних) соединений. Например, рассмотрим следующую команду:

SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

Хотя ограничения данного запроса внешне схожи с предыдущим примером, их семантика различается, так как для каждой строки таблицы A, не имеющей соответствия в соединении таблиц B и C, должна быть выведена пустая строка. Таким образом, у планировщика отсутствует выбор порядка соединения: он обязан выполнить соединение B с C, а затем присоединить таблицу A к полученному результату. Соответственно, планирование данного запроса занимает меньше времени, чем предыдущего. В других случаях планировщик может определить, что существует несколько безопасных порядков соединения. Например, для выражения:

SELECT * FROM a LEFT JOIN b ON (a.bid = b.id) LEFT JOIN c ON (a.cid = c.id);

допустимо сначала соединить A с B или A с C. В настоящее время только FULL JOIN полностью определяет порядок соединения. Большинство практических случаев, связанных с использованием LEFT JOIN так и RIGHT JOIN допускают перестановку в определенной степени.

Явный синтаксис внутреннего соединения (INNER JOIN, CROSS JOIN, или обычное JOIN) семантически эквивалентно перечислению входных отношений в Предложение FROM, поэтому такой синтаксис не ограничивает порядок соединения.

Несмотря на то, что большинство типов JOIN не накладывают жестких ограничений на порядок соединения, можно дать указание планировщику Digital Q.DataBase планировщик рассматривает все JOIN предложения запроса как ограничивающие порядок соединения. Например, следующие три запроса логически эквивалентны:

SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
SELECT * FROM a CROSS JOIN b CROSS JOIN c WHERE a.id = b.id AND b.ref = c.id;
SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

Но если указать планировщику на необходимость соблюдения JOIN порядка, планирование второго и третьего запросов займет меньше времени, чем первого. Этим эффектом можно пренебречь при использовании всего трех таблиц, однако он может иметь решающее значение при работе с большим количеством таблиц.

Для принудительного следования планировщика порядку соединения, заданному явными JOINпредложениями JOIN, установите join_collapse_limit параметр времени выполнения в значение 1. (Другие возможные значения рассматриваются ниже.)

Для сокращения времени поиска нет необходимости полностью ограничивать порядок соединения, так как допускается использование JOIN операторов внутри элементов обычного Предложение FROM списка. Рассмотрим, например:

SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;

При join_collapse_limit = 1 это вынуждает планировщик выполнить соединение A с B перед их соединением с другими таблицами, но в остальном не ограничивает его выбор. В данном примере количество возможных порядков соединения сокращается в 5 раз.

Подобное ограничение области поиска планировщика является полезным приемом как для сокращения времени планирования, так и для направления планировщика к эффективному плану выполнения запроса. Если планировщик по умолчанию выбирает неудачный порядок соединения, можно принудительно задать более подходящий порядок, используя JOIN синтаксис — при условии, что вам известен лучший порядок. Рекомендуется проведение экспериментов.

Схожей проблемой, влияющей на время планирования, является подстановка подзапросов в родительский запрос. Рассмотрим, например:

SELECT *
FROM x, y,
    (SELECT * FROM a, b, c WHERE something) AS ss
WHERE somethingelse;

Подобная ситуация может возникнуть при использовании представления, содержащего соединение; правило SELECT будет вставлено вместо ссылки на представление, что приведет к формированию запроса, аналогичного приведенному выше. Обычно планировщик пытается встроить подзапрос в родительский запрос, в результате чего получается:

SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;

Это обычно приводит к более эффективному плану, чем отдельное планирование подзапроса. (Например, внешние WHERE условия могут быть такими, что предварительное соединение X с A позволит исключить многие строки A, избавляя от необходимости формировать полный логический результат подзапроса.) Однако одновременно с этим увеличивается время планирования; в данном случае задача поиска пути пятистороннего соединения заменяет две отдельные задачи трехстороннего соединения. Из-за экспоненциального роста числа вариантов это имеет существенное значение. Планировщик старается избегать застревания на масштабных задачах поиска соединений, не выполняя встраивание подзапроса, если более чем from_collapse_limit Предложение FROM элементов приведет к формированию родительского запроса. Можно найти компромисс между временем планирования и качеством плана, увеличивая или уменьшая этот параметр времени выполнения.

from_collapse_limit и join_collapse_limit имеют схожие названия, поскольку выполняют практически идентичные функции: один из них определяет, когда планировщик будет «разворачивать» подзапросы, а другой — когда он будет разворачивать явные соединения. Как правило, следует либо установить join_collapse_limit равным from_collapse_limit (чтобы явные соединения и подзапросы обрабатывались единообразно), либо установить join_collapse_limit в значение 1 (если требуется контролировать порядок соединений через явные соединения). Но их можно настроить и по-разному, если необходимо оптимизировать соотношение между временем планирования и временем выполнения.

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению