Программирование >>  Полное сканирование таблицы 

1 ... 52 53 54 [ 55 ] 56 57 58 ... 107


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

ПРИМЕЧАНИЕ

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

Специальные правила для особых случаев

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

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

Значения детальных коэффициентов соединения велики, намного больше 1,0. Так как главные коэффициенты соединения (вниз по дереву соединения) никогда не превышают 1,0, будет гораздо безопаснее, если вы произведете как можно больше соединений вниз перед переходом к соединениям в верхнем направлении, даже если во втором случае вы получаете доступ к большему количеству фильтров. Обычно фильтры для узлов, расположенных в верхней части дерева, отбрасывают не больше строк, чем база данных выбирает, переходя к более детальной таблице. Даже когда детальные коэффициенты соединения невелики, сама природа соединения один ко многим , обеспечивает вероятность того, что эти значения могут существенно возрасти в будущем или на других машинах, где выполняется то же самое приложение. Поэтому для большого коэффициента детализированного соединения лучше выбирать надежный SQL-код, кроме тех случаев, когда вы полностью уверены, что локальная, текущая статистика не изменится со временем и будет одинакова для различных наборов данных.

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



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

Главные коэффициенты соединения равны 1,0 или достаточно близки к этому значению, чтобы разница не играла роли. Это относится к распространенному случаю, когда не равные нулевому значению внешние ключи детальных таблиц обладают превосходной целостностью ссылочных данных.

Когда таблицы достаточно велики, чтобы эффективность имела большое значение, то существует один коэффициент фильтрации, намного меньший всех остальных. Редко встречаются две таблицы с практически одинаковым коэффициентом фильтрации. Если таблицы велики, а результат вьшолнения запроса относительно мал, как обычно бывает с полезными результатами запросов, то произведение всех коэффициентов фильтрации должно быть небольшим. Гораздо проще получить этот небольшой результат при помощи одного селективного фильтра, иногда в сочетании с несколькими достаточно не селективными фильтрами, чем при помощи большого количества схожих полуселективных фильтров. Поиск разумных (в терминах ведения бизнеса) объяснений большому количеству полуселективных фильтров оказывается неблагодарным делом, и я мог бы сосчитать количество раз, когда встречался с подобными случаями за 10 лет настройки SQL, по пальцам одной руки. Имея один фильтр, обладающий намного большей селективностью, чем остальные, гарантировать считывание минимального количества строк из самой важной корневой детальной таблицы можно, если начать выполнение запроса с таблицы с наилучшим фильтром.

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

В следующих разделах добавлены правила для обработки редких специальных случаев, которые противоречат этим предположениям.

Безопасные декартовы произведения

Рассмотрим запрос, диаграмма для которого показана на рис. 6.14. Выполняя обычные правила (и выбирая первым самый левый узел, просто для удобства), мы переходим к фильтру для Т1 и присоединяем Т1 к М, используя индекс по внешнему ключу, указывающему на Т1. Затем мы переходим к Т2, используя индекс по первичному ключу, и в конце отбрасываем строки, не проходящие




1Г 11

Tiooi т2ао1

Рис 6.14. Запрос с потенциально хорошим планом выполнения с декартовым произведением

Описанный план затронет 1 строку в Т1,1000 строк в М (1 % от общего количества) и 1000 строк в Т2 (в среднем каждая строка из Т2 нужна 10 раз) перед тем, как отбросить из результата все строки, оставив лишь 10. Если аппроксимировать стоимость запроса как количество полученных из таблиц строк, то она составит 2001. Однако если пойти против правил, то можно получить план, который не следует связям, обозначающим соединения. Можно выполнить вложенные циклы между Т1 и Т2, используя соответствующие фильтрующие индексы. Поскольку между Т1 и Т2 нет соединения, в результате мы получим декартово произведение всех строк, удовлетворяющих условию фильтрации для Т1 и всех строк, удовлетворяющих условию фильтрации для Т2. Для данных размеров таблиц результирующий план выполнения считает лишь по одной строке из Т1 и Т2. Выполнив декартово соединение Т1 и Т2, база данных сможет использовать индекс по внешнему ключу, которые указывает на Т1, чтобы перейти к М и считать из нее 1000 строк. Затем база данных отбросит 990 строк, не удовлетворяющих условию соединения для М и Т2.

ПРИМЕЧАНИЕ

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

С использованием декартова произведения стоимость плана составит лишь 1002, если за функцию стоимости принять количество считанных строк.

Что же произойдет, если размеры таблиц удвоятся? Стоимость исходного плана, следующего связям для соединений, удвоится, составив 4002, что пропорционально количеству возвращенных запросом строк, которое также удваивается. Это нормально для надежных планов, стоимость которых пропорциональна количеству возвращенных строк. Однако план с декартовым произведением резко ухудшается: база данных считает 2 строки из Т1, затем для каждой из этих строк считает по 2 строки из Т2 (всего 4 строки), и затем, с декартовым произведением, состоящим из 4 строк, считает 4000 строк из М. Стоимость запроса, 4006, теперь практически равна стоимости обычного плана. Еще раз удвоив размеры таблиц, мы получим, что стоимость стандартного плана становится равной 8004, а плана с декартовым произведением - 16 020. Это демонстрирует ненадежность большинства планов выполнения с декартовым произведением, которые

через фильтр для 12. Если предположить, что в Т1 100 строк, то, на основании коэффициентов соединения, в М должно быть 100 ООО строк, и в Т2 - также 100 строк.



1 ... 52 53 54 [ 55 ] 56 57 58 ... 107

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика