|
Программирование >> Полное сканирование таблицы
ние запроса. Однако узлы, представляющие главные таблицы, находящиеся под представлением (например, узел С на рис. 7.34), могут быть присоединены к любому узлу скелета определения представления, в зависимости от того, какая таблица содержит внешний ключ, указывающий на этот главный узел. Добавим явные числовые коэффициенты фильтрации ко всем узлам в скелете запроса, имеющим фильтры - как в запросе, определяющем представление, так и в запросе, использующем его. На рис. 7.34 коэффициент фильтрации 0,3 рядом с узлом О появляется благодаря фильтру в определяющем представление запросе, а коэффициент фильтрации 0,0002 рядом с узлом С - благодаря условиям на имя и фамилию покупателей в использующем представление запросе. (SV) (OVV ODT 0.8 Т1 Рис. 7.34. Нерасширенная диафамма запроса, использующего представление Результат должен выглядеть как на рис. 7.35. Там я добавил звездочку к левому узлу С, чтобы указать на различие между узлами, имеющими одинаковые имена И снова я использовал ту же статистику для фильтра по имени покупателя, что и в схожем примере на рис. 5.5, чтобы получить коэффициент фильтрации 0,0002 рядом с С внутри правого скелета представления. \с 0.0002 от; Рис 7.35. Расширенная диаграмма запроса, использующего представление Итак, мы завершили диаграмму, которая потребуется для перехода к фактической настройке запроса, использующего представления, для чего необходимо определить, нужно ли для получения оптимального плана изменить определяющий представление или использующий представление запрос. Настройка запросов с представлениями Обычно оптимальный план исполнения для запроса, использующего представления - это план, который бы вы составили для соответствующей диаграммы запроса к простым таблицам. Однако вам придется решить четьфе проблемы. Некоторые соединения со сложными представлениями трудно представить как простые соединения с простыми таблицами. В частности, внешние соединения с представлениями, в которых есть соединения в запросах, определяющих представления, сложно выражать, используя простые соединения. Эта проблема касается нашего примера, поэтому я рассмотрю ее подробнее в следующем разделе Внешние соединения с представлениями . Некоторые представления используют в точности те же строки той же таблицы, что и другая таблица в запросе, использующем представления, что создает излишнюю работу для базы данных, которую вам придется устранить. Это происходит с узлами С* и С на рис. 7.35, поэтому данная проблема будет рассматриваться позднее. Преимущество представлений с точки зрения упрощения разработки заключается в том, что они скрывают сложность запросов, но это преимущество также позволяет незаметно создавать в коде избыточные соединения, которые были бы очевидны и потребовали бы большей работы по кодированию, если бы разработчики использовали только простые таблицы. Узлы внутри определяющих представления запросов и соединения с ними часто оказываются ненужными для получения результата, необходимого в использующем представления запросе. Использование представлений ограничивает ваши возможности управления планом исполнения. Если вы измените определяющий представление запрос, чтобы улучшить план исполнения запроса, использующего представление, то можете ненамеренно ухудшить производительность других запросов, использующих то же самое представление. Вы всегда можете создать новое представление, ис1спючительно для удобства использования одного запроса, но это противоречит преимуществу представлений, которое заключается в совместном использовании кода. В целом, подсказки SQL и прочие изменения в запросе, использующем представления, не могут улучшить контроль над тем, как база данных обращается к таблицам в запросе, определяющем представление. Иногда для получения необходимого плана вам приходится исключать использование представлений. Внешние соединения с представлениями Возвращаясь к предыдущему примеру, рассмотрим, что же означает наличие внешнего соединения с представлением Shipment V, которое само по себе является внутренним соединением между таблицами Shipments и Addresses. Так как база данных должна считать, что существует реальная таблица с точно теми строками, которые найдет представление, соединение обнаруживает внутреннее соединение для значений Shi pment ID, которые присутствуют в Shi pments и указывают на поставки, поле Add ress I D для которых успешно соединяется с таблицей Addresses. Если база данных не может провести успешное соединение одновременно и с Shi pments, и с Addresses, то соединение с представлением становится полностью внешним (с обеими таблицами), даже если первое соединение с Shipments могло пройти успешно. При поиске плана со вложенными циклами база данных не может знать, будет ли для внешнего соединения найден внутренний случай, пока не проведет успешное соединение с обеими таблицами в запросе, определяющем представление. К сожалению, это все слишком сложно, чтобы такой случай мог быть обработан автоматически сгенерированным кодом, поэтому ваша база данных может просто сдаться и отказаться искать план с вложенными циклами. Вместо этого сервер базы данных понимает, что не так уж важно, насколько сложна лежащая в основе запроса логика. Эта логика функционально не сможет сделать никакой ошибки, если, просто получит все строки из запроса, определяющего представление, и обработает результат как реальную таблицу. Для внешнего соединения с представлением база данных обычно выполняет соединение методом сортировки слиянием или соединение хэшированием с временно созданной таблицей. Это достаточно безопасно в плане функциональности, но обычно становится кошмаром для производительности, кроме тех случаев, когда сам по себе запрос, определяющий представление, достаточно быстр. ВНИМАНИЕ - В качестве основного правила для улучшения производительности избегайте внешних соединений с любыми представлениями, более сложными, чем SELECT <Списон лростых СТОЛбцов> FROM <Оциа табтца>. Схожие проблемы возникают для всех типов соединений с представлениями, в которых в определяющем представление запросе присутствуют UNION или GROUP BY. Однако соединения, исходящие от подобных представлений, когда в них есть таблица, которую можно выбрать ведущей таблицей запроса, обычно работают прекрасно. Снова рассмотрим использующий представление запрос из предыдущего подраздела. Если вы поместите определяющий представление запрос для Shi pmentV в запрос, использующий представления, чтобы разрешить проблему производительности с внещним соединением, то, вероятно, получите такой результат: SELECT OV.Customer Main Phone. C.Honorlfic. OV.Customer First Name. 0\/.Customer Last Name. С.Suffix. OV.Customer Acldress ID. A.AddressID Shi pment Address ID, A.Street Addr Linel Shipment Street Address Linel, A.Street Addr Line2 Shipment Street Address Line2. A.City Name Shipment City Name. A.State Abbreviation ShipmentState. A.ZIP Code Shipment ZIP, OD.Deferred Ship Date. DD.Item Count. ODT.Text. P.Prod Description. S.ShipmentOate FROM Recent Drder V OV. Drder Details OD. Products P. Shipments S, Addresses A. Codejranslations ODT, Customers С WHERE UPPER(OV.Customer LastJiame) LIKE :last nameX AND UPPERCOV.CustomerJirst Name) LIKE :first nameHS; AND OD.OrderJD = OV.Order ID AMD OV. Customer JD = C.Customer ID AND OD.Product ID = P.Product ID(+) AND OD.Shipment ID = S.Shipment ID(+) AND S.Address ID = A.Address ID(+) AND OD. Status Jode = ODT. Code AND ODT.Codejype = ORDER DETAIL STATUS ORDER BY OV. Customer JD. OV.0rder ID Desc. S.Shipment ID. OD.OrderJetail ID К сожалению, этот код не позволяет получить тот же результат, что и исходный запрос, из-за специфики внешнего соединения с представлением. В частности, исходный запрос возвращает значение Shi pmentDate, равное null, если полное представление, включая соединение с Addresses, не может успешно соединиться с Orderjetai Is. Таким образом, если для перевозки (shipment) не указано допус-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |