|
Программирование >> Полное сканирование таблицы
скелетом запроса (или изолированным узлом), отдельной виртуальной таблицей. С этой точки зрения база данных возвратит все комбинации строк из двух независимых запросов. То есть вы получите декартово произведение. Столкнувшись с декартовым произведением, например с показанным на рис. 7.9, необходимо исследовать причину его возникновения. Узнав причину, вы можете решить, какие действия предпринимать в зависимости от того, с каким из четырех случаев несвязных запросов встретились. В запросе отсутствует соединение между не связанными частями. В этом случае необходимо просто добавить отсутствующее соединение. Запрос объединяет два независимых запроса, каждый из которых возвращает несколько строк. Здесь избежать появления декартова произведения можно, выполнив независимые запросы по отдельности. Один из независимых запросов возвращает одну строку. Рассмотрите вариант разделения запросов, чтобы сохранить производительность базы данных, особенно если второй независимый запрос возвращает много строк. Сначала выполните однострочный запрос. Оба независимых запроса возвращают по одной строке. В этом случае просто оставьте запрос несвязным, если только он не ставит вас в тупик или его не сложно обрабатывать. Перед тем как превращать несвязный запрос в два разных запроса, посмотрите, не забыл ли случайно разработчик одно из соединений. На ранней стадии цикла разработки самая распространенная причина появления несвязных диаграмм запросов заключается в том, что разработчики просто забывают некоторые операторы соединения, которые связывают разъединенные поддеревья. В таком случае нужно просто добавить отсутствующее условие соединения, после чего у вас больше не будет несвязного дерева. Если у одной из таблиц в дереве есть внешний ключ, указывающий на первичный ключ корневого узла второго дерева, то практически точно это соединение было по невнимательности забыто. Если каждый из независимых запросов возвращает несколько строк, то количество комбинаций превзойдет количество строк, которые вы бы получили, выполнив два запроса независимо. Однако набор комбинаций двух результатов содержит не больше информации, чем вы бы получили при раздельном выполнении запросов, поэтому работа по созданию избыточных данных - это всего лишь потеря времени, по крайней мере, с точки зрения получения сырых данных. Поэтому, возможно, лучше вьшолнить два запроса по отдельности. Иногда есть причины, хоть как-то оправдьшающие создание комбинаций декартова произведения с точки зрения удобства программирования. Но всегда есть обходные пути, позволяющие избежать лишних данных, если их стоимость не оправданна. ПРИМЕЧАНИЕ Если бы вы беспокоились только о физическом вводе-выводе, то декартово произведение было бы допустимо, так как излишние считывания данных из повторяющегося запроса практически всегда полностью кэшированы после первого считывания. В действительности некоторые разработчики даже защищают подобные долго выполняющиеся примеры запросов, оправдывая их низкой стоимостью физического ввода-вывода. Подобные запросы - отличный способ нагрузить процессор и создать чудовищное количество операций логического ввода-вывода, если вам когда-либо понадобится это, - например, для нагрузочных испытаний или других лабораторных исследований, но им нет места в бизнес-приложениях. Если один из независимых запросов гарантированно возвращает единственную строку, то декартово произведение будет, по крайней мере, безопасным и гарантированно вернет не больше строк, чем второй независимый запрос. Однако при комбинировании запросов потенциально существует и небольшая стоимость работы при получении данных через сетевое соединение с сервером, так как список выбора комбинированного запроса может возвращать данные из небольшого запроса несколько раз по одному для каждой строки, возвращаемой большим запросом. А это требует пересылки большего количества байт, чем при использовании разъединенных запросов. Эти затраты пропускной способности определенным образом противопоставляются экономии времени ожидания сети. Комбинированный запрос экономит повторные обращения к базе данных по сети, поэтому выбор зависит от деталей запроса. Если вы не разъедините запросы, то оптимальный план прост. Сначала необходимо выполнить оптимальный план для запроса, возвращающего одну строку. Затем, при помощи вложенного цикла, который выполняется всего один раз, выполнить оптимальный план для запроса, возвращающего несколько строк. Этот комбинированный план исполнения стоит столько же, сколько и выполнение двух запросов независимо. Если же вместо этого вы выполните план для запроса, возвращающего несколько строк, первым, то план со вложенным циклами потребует повторного вьшолнения плана для запроса, возвращающего одну строку, - по одному разу для каждой строки, возвращенной другим запросом. Комбинирование запроса, возвращающего одну строку, с запросом, возвращающим несколько записей, иногда и удобно, и оправданно. Существует специальный случай, соответствующий правой части рис. 7.9, когда запрос, возвращающий одну строку - это просто считьшание одной строки из изолированной таблицы 12, для которой вообще нет соединений. Декартово произведение иногда полезно для выбора параметров, хранящихся в однострочной таблице параметров. Особенно когда эти данные упоминаются только в разделе WHERE, а не в списке SELECT. Если запрос не возвращает данные из таблицы параметров, то дешевле выполнить правильно скомбинированный запрос, чем отдельные запросы. Еще более редкий случай гарантирует, что оба изолированных запроса возвращают по одной строке. В этом случае, когда нет никаких опасностей, присутствующих в остальных случаях, комбинирование запросов будет абсолютно безопасным с точки зрения производительности. Однако с точки зрения программирования и поддержки программного обеспечения комбинирование подобных запросов может быть слишком запутанным, а экономия будет небольшая. Диаграммы запросов с несколькими корневыми узлами На рис. 7.10 показан пример диаграммы запроса, нарушающей предположение о наличии одного корневого узла у дерева запроса. Этот случай сродни предьщу-щему случаю (несвязные диаграммы запросов). Здесь для каждой строки таблицы Master, удовлетворяющей условию запроса, запрос вернет все комбинации соответствующих детальных строк из Recti и Root2. С данными детальными коэффициентами соединения можно ожидать, что все комбинации 5 детализированных строк из Root 1 и 30 строк из таблицы Root2 дадут 150 комбинированных строк для каждой соответствующей строки из Master. Эти 150 строк содержат не больше исходных данных, что 5 строк из Rootl и 30 строк из Root2 вместе, поэтому будет быстрее считать 5 и 30 строк по отдельности, избежав декартова произведения. Тогда как несвязные диаграммы запросов генерируют одно большое декартово произведение, несколько корневых узлов приводят к появлению целых наборов небольших декартовых произведений, по одному для каждой соответствующей главной строки. Root2 Рис. 7.10. Диаграмма запроса с несколькими корнями Есть четыре возможных случая появления диаграммы запроса с несколькими корнями. В следующем списке перечислены эти случаи и описаны подходящие решения. 1. Отсутствующее условие. В этом запросе отсутствует условие, которое преобразовало бы одну из корневых детальных таблиц в главную таблицу, превратив соединение один ко многим в один к одному . Решение: добавить отсутствующее условие соединения. 2. Декартово произведение многие ко многим . Подобный запрос представляет декартово произведение многие ко многим для каждой главной строки, которое возникает между детальными таблицами, относящимися к одной главной таблице. Этот случай скрывается под маской превышающих 1,0 детальных коэффициентов фильтрации от одной главной таблицы к двум различным корневым детальным таблицам. Решение: избавьтесь от декартова произведения, разделив запрос на независимые запросы, которые считывают две корневые детальные таблицы по отдельности. 3. Детальный коэффициент соединения меньше 1,0. В этом случае одна из корневых детальных таблиц соединяется с общей главной таблицей с детальным коэффициентом соединения, меньшим 1,0. Решение: хотя этот случай не создает проблем для производительности, рассмотрите вариант разъединения частей запроса или превращения одной из частей запроса в подзапрос, по функциональным причинам. 4. Таблица используется только для проверки существования каких-либо сущностей. Одна из корневых детальных таблиц не поставляет никаких данных, нужных в списке SELECT, и включена только для проверки существования. Решение: превратите проверку существования в явный подзапрос.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |