Шрифт:
Интервал:
Закладка:
SELECT
ID,
TITLE as PUBLICATION,
'BOOK ' AS PUBLICATION_TYPE,
CAST (AUTHOR_LAST_NAME || ' ' || AUTHOR_FIRST_NAMES AS VARCHAR (50) )
AS AUTHOR_EDITOR,
EDITION AS EDITION_OR_ISSUE,
PUBLICATION_DATE DATE,
PUBLISHER_ID,
CAST(ISBN AS VARCHAR(14)) AS ISBN,
LIST_PRICE
FROM CURRENT_TITLES
WHERE ...
UNION SELECT
ID,
TITLE,
'PERIODICAL',
EDITOR_LAST_NAME || ' , ' || EDITOR_FIRST_NAMES AS AUTHOR_EDITOR,
CAST (AUTHOR_LAST_NAME || ', ' || AUTHOR_FIRST_NAMES AS VARCHAR(50)),
ISSUE_NUMBER,
PUBLICATION_DATE,
PUBLISHER_ID, 'Not applicable',
LIST_PRICE
FROM PERIODICALS
WHERE ...
ORDER BY 2;
Условия поиска и упорядочивания
Обратите внимание в предыдущем примере, что условия поиска возможны в каждой объединяемой спецификации SELECT. Они являются обычными выражениями поиска, которые должны соответствовать объединяемому набору, управляемому текущим выражением SELECT. Не существует способа коррелировать условия поиска в пределах поднаборов.
Допустимо только одно предложение упорядочения, оно должно следовать после всех поднаборов. Синтаксис ORDER BY номер (т. е. упорядочение по номеру столбца) требуется для упорядочения объединяемых наборов.
Реентерабельные запросы UNION
Возможно обращение к реентерабельной технике для создания объединяющего запроса, который извлекает несколько поднаборов из одной таблицы. Алиасы таблиц требуются в предложениях FROM, но ссылки на колонки не обязательно должны быть полностью специфицированы. Возвращаясь к нашей таблице CURRENT_TITLES, предположим, что мы хотим получить список заголовков книг в зависимости от цены. Реентерабельный запрос должен выглядеть приблизительно следующим образом:
SELECT
ID,
TITLE,
CAST ('UNDER $20' AS VARCHAR(IO)) AS RANGE,
CAST (AUTHOR_LAST_NAME || ', ' || AUTHOR_FIRST_NAMES AS VARCHAR (50) )
AS AUTHOR,
EDITION,
LIST_PRICE
FROM CURRENT_TITLES CT1
WHERE LIST_PRICE < 20.00
UNION SELECT
ID,
TITLE,
CAST ('UNDER $40' AS VARCHAR(IO),
CAST (AUTHOR_LAST_NAME || ', ' || AUTHOR_FIRST_NAMES AS VARCHAR(50) ) ,
EDITION,
LIST_PRICE
FROM CURRENT_IITLES CT2
WHERE LIST_PRICE >= 20.00 AND LIST_PRICE < 40.00
UNION SELECT
ID,
TITLE,
CAST ('$40 PLUS' AS VARCHAR(IO) ) ,
CAST (AUTHOR_LAST_NAME || ', ' || AUTHOR_FIRST_NAMES AS VARCHAR(50) ) ,
EDITION,
LIST_PRICE
FROM CURRENT_TITLES CT3
WHERE LIST PRICE >= 40.00;
UNION ALL
Если в процессе создания объединенного набора были сформированы дублированные строки, то поведение по умолчанию - исключение из набора дублированных строк. Для включения дубликатов используйте UNION ALL вместо UNION.
Темы оптимизации: планы запросов и оптимизатор
В этом разделе рассматривается подсистема оптимизатора Firebird и те стратегии, применяемые им для создания планов запроса, которые будут использованы сервером для операторов SELECT и подзапросов во время выполнения. Мы вкратце рассмотрим синтаксис плана запроса, а также некоторые способы передачи ваших собственных планов серверу.
Планы и оптимизатор запросов Firebird
Для выполнения оператора SELECT или условия поиска сервер Firebird преобразует оператор в набор внутренних алгоритмов, называемых оптимизированным запросом. Каждый раз, когда оператор подготавливается для выполнения, оптимизатор вычисляет план поиска.
ПланПлан запроса создает некий вид дорожной карты, которая сообщает серверу наименее дорогостоящую дорогу для требуемого процесса поиска, сортировки и поиска соответствия запрашиваемому результату. Чем более эффективный план сконструирует оптимизатор, тем быстрее оператор начнет возвращать результаты.
План создается в соответствии с наличием доступных индексов, с тем способом, каким индексы или потоки соединяются или сливаются, а также с методом поиска (методом доступа).
При вычислении плана оптимизатор будет просматривать каждый доступный индекс, выбирая или отвергая индексы в соответствии с их стоимостью. Помимо существования индекса он принимает во внимание другие факты, такие как размер таблицы, степень распределения различных значений в индексе. Если оптимизатор может определить, что использование индекса будет требовать больше издержек, чем последовательный просмотр строки за строкой в потоке, он может принять решение проигнорировать индекс, в пользу последовательного формирования промежуточного потока или создания потока естественным образом.
Выражения планаДля элементов плана в SQL Firebird применяет такой же синтаксис, какой он использует для передачи серверу. Понимание сгенерированных оптимизатором планов может быть очень полезным как для предвидения, каким образом оптимизатор будет решать конкретную задачу, так и в качестве основы для написания пользовательских планов.
Синтаксис выражений планаШаблон синтаксиса для фразы PLAN:
<спецификация-запроса> PLAN <выражение-плана>
Этот синтаксис позволяет задавать одно отношение или соединение двух или более отношений за один раз. Могут быть использованы вложенные скобки для задания любых комбинаций соединений. Операции передают свои результаты в выражении слева направо.
СимволыВ используемой здесь нотации круглые скобки и запятые являются элементами синтаксиса. Фигурные скобки, квадратные скобки и символ вертикальной черты не являются частью синтаксиса- как и в ранее описанном синтаксисе они указывают, соответственно, обязательные и необязательные фразы и взаимоисключающие варианты.
plan-expression := [join-type] (plan-item-list)
join-type := [JOIN] | [SORT] [MERGE]
plan-item-list := plan-item | plan-item, plan-item-list
plan-item := table-identifier access-type | plan_expression
table-identifier := { table-identifier | alias-name } [table-identifier]
access-type := { NATURAL | INDEX (index-list) | ORDER index-name }
index-list := index-name | index-name, index-list
ЭлементыТип соединения (join-type) может быть JOIN или MERGE.
* Тип соединения по умолчанию JOIN (т. е. соединение двух потоков с использованием индекса правого потока для поиска соответствующих ключей в левом потоке).
* MERGE выбирается, если нет используемых индексов. В этом случае два потока сохраняются в соответствующем порядке, а затем сливаются. В пользовательских планах скорость поиска будет увеличена при задании такого типа соединения, когда нет доступных индексов.
Идентификатор таблицы (table-identifier) задает поток. Он должен быть именем таблицы базы данных или алиасом. Если одна и та же таблица будет использована более одного раза, для нее должен быть указан алиас для каждого использования. Алиас должен следовать после имени таблицы при ее первом упоминании. Для спецификации базовых таблиц в просмотре синтаксис предоставляет возможность давать таблицам множество идентификаторов. Планы для просмотров обсуждаются в главе 24.
Тип доступа (access-type) должен быть одним из следующих:
* NATURAL - доступ к строкам осуществляется последовательно, без какого-либо особого порядка. Это тип доступа по умолчанию, он может быть опущен, тем не менее разумно включить его в пользовательский план для документирования;
* INDEX - позволяет указать один или более индексов для вычисления предикатов и проверки условий соединения в запросе;
* ORDER- указывает, что результат запроса должен быть отсортирован (упорядочен) по самому левому потоку с использованием индекса.
Элемент плана (plan-item) включает в себя план доступа, а также идентификатор таблицы или ее алиас.
ОптимизаторЕсли вы не очень хорошо знакомы с планами запросов, вы, вероятно, будете удивлены, как весь этот синтаксис может транслироваться в план. Чуть позже синтаксис станет более осмысленным, когда мы посмотрим на некоторые планы, сгенерированные оптимизатором. Тем не менее в настоящий момент будет полезным посмотреть, как оптимизатор использует "материал" для его операций: соединения и условия поиска, требуемые в операторе, потоки, лежащие в основе спецификации запроса, и доступные индексы.
Факторы в оценке преобразований (вычислений)Цель оптимизатора - создать отражающий стратегию план, который, в соответствии с некоторыми факторами, скорее всего, начнет выдавать выходной поток наиболее быстрым образом. Вычисление плана может оказаться довольно неточным при использовании некоторых переменных, которые могут дать только приблизительную оценку. Рассматриваемые факторы включают:
* доступность индекса и селективность этого индекса. Фактор селективности, используемый в оценках, выбирается из системных таблиц при открытии базы данных. Даже в начале работы он может быть неверным, поскольку может изменяться в процессе операций обширных изменений, выполненных с момента последнего вычисления селективности;
* количество строк в таблицах потоков;
* существует ли критерий выбора, и если да, существует ли доступный или подходящий индекс;
* необходимость выполнения сортировок, как промежуточных (для слияния), так и окончательной (для упорядочения и группирования).
ПотокиПрименение термина "поток", который возникает при обсуждении оптимизатора, является просто общим способом наименования множества строк. Набор может содержать все строки и столбцы таблицы или это может быть подмножество данных таблицы, ограниченное некоторым образом спецификациями столбцов и условиями поиска. В процессе обработки запроса сервер может из существующего потока создавать новые потоки, такие как внутренний сортированный набор или набор значений подзапроса для сравнения IN(). См. также далее разд. "Реки".
- Delphi. Учимся на примерах - Сергей Парижский - Программирование
- Сделай видеоигру один и не свихнись - Слава Грис - Программирование / Руководства
- Психбольница в руках пациентов - Алан Купер - Программирование