Планы выполнения для баз данных - PullRequest
1 голос
/ 21 октября 2009

Вопрос 1:

Когда мы выполняем запрос, меняется ли план выполнения каждый раз при выполнении запроса?

Если да, какой-нибудь удар по производительности?

Если нет, то если мы что-то изменим в таблице, т.е. добавим индекс, как база данных узнает, что есть что-то, что можно использовать для изменения плана выполнения для более быстрого выполнения?

ВОПРОС 2:

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

Ответы [ 3 ]

2 голосов
/ 21 октября 2009
  • Если быть точным для SQL Server :

У вас есть не более двух планов в кеше (один параллельный, один непараллельный). Затем план используется с контекстом исполнения на пользователя. Больше информации в моем ответе здесь

  • Порядок присоединения не имеет значения почти во всех случаях

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

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

0 голосов
/ 21 октября 2009

Объединения выполняются не в порядке, основанном на внутреннем и внешнем, а скорее на том, что, по мнению оптимизатора, приведет к тому, что запрос будет выполнен быстрее всего. Детали будут варьироваться в зависимости от базы данных. Но в основном оптимизатор запросов пытается оптимизировать использование индексов.

Предположим, у вас был этот запрос:

select a.foo, b.bar
from a
join b on b.b_id=a.b_id
where a.some_number=42;

Теперь предположим, что у вас есть уникальный индекс для b.b_id, но нет индекса для a.some_number.

Тогда у оптимизатора запросов есть два варианта: он может выполнить последовательное чтение полного файла на b, а затем для каждого b выполнить последовательное чтение полного файла при поиске совпадения по b_id и some_number = 42. То есть читать записи ^ b. Или он мог бы выполнить последовательное чтение всего файла при поиске some_number = 42, затем для каждого a он мог бы использовать индекс для быстрого поиска записи из b с совпадающим b_id. То есть прочитайте * 2 записи. Ну, очевидно, второй план намного лучше, так что это то, что он выберет.

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

0 голосов
/ 21 октября 2009

(Предполагая, что SQL Server здесь, вы не указали ...)

Планы выполнения кэшируются, и в той степени, в которой вы параметризируете свои запросы, можно использовать повторно.

Когда вы изменяете базовую таблицу или индексы, SQL Server знает дату изменения этих вещей в сравнении с кэшированным планом выполнения и может пересмотреть запрос для новых условий. То же самое, когда статистика обновляется ... иногда фактические данные определяют план, а не только дизайн таблицы / индекса.

...