|
| ||||||||||||
| ||||||||||||
|
2010 г.
Преобразование запросов, основанное на стоимостиРафи Ахмед, Эллисон Ли, Эндрю Витковски, Динеш Дас, Хонг Су, Мохамед Зэйд, Тьерри Крюейнс Перевод Леонида Борчука
Оригинал: Cost-Based Query Transformation in Oracle / Rafi Ahmed, Allison Lee, Andrew Witkowski, Dinesh Das, Hong Su, Mohamed Zait, Thierry Cruanes // Proceedings of the 32nd international conference on Very large data base, 2006, pp. 1026 — 1036 2.2. Преобразования, основанные на оценке стоимостиЗдесь мы кратко остановимся на некоторых из преобразований, которые выполняются в Oracle на основе оценки стоимости. 2.2.1. Устранение вложенности подзапросов
В случае многотабличных подзапросов с
Q1
SELECT e1.employee_name, j.job_title
FROM employees e1, job_history j
WHERE e1.emp_id = j.emp_id and
j.start_date > '19980101' and
e1.salary > (SELECT AVG (e2.salary)
FROM employees e2
WHERE e2.dept_id = e1.dept_id) and
e1_dept_id IN (SELECT dept_id
FROM departaments d, locations l
WHERE d.loc_id = l.loc_id and
l.country_id = 'US');
Рассмотрим преобразованный запрос Q10, в котором вложенность первого подзапроса устранена за счет образования встроенного представления.
Q10
SELECT e1.employee_name, j.job_title
FROM employees e1, job_history j,
(SELECT AVG (e2.salary) avg_sal, dept_id
FROM employees e2
GROUP BY dept_id) V
WHERE e1.emp_id = j.emp_id and
j.start_date > '19980101' and
e1.dept_id = V.dept_id and
e1.salary > V.avg_sal and
e1_dept_id IN
(SELECT dept_id
FROM departaments d, locations l
WHERE d.loc_id = l.loc_id and
l.country_id = 'US');
Непреобразованный запрос Q1 может лучше выполняться с использованием стратегии TIS, если внешний блок запроса значительно сокращает число кортежей таблицы Преобразование, основанное на оценке стоимости, было введено в Oracle 10g. В версиях, предшествующих Oracle 10g, устранение вложенных подзапросов с образованием встраиваемых представлений основывалось на эвристиках. Немного упрощенный вариант этого эвристического правила можно сформулировать следующим образом: если во внешнем запросе имеются предикаты фильтрации и существуют индексы на локальных столбцах предиката корреляции подзапроса, то вложенность подзапроса устранять не следует. В подразделе 4.1 мы приводим результаты производительности преобразований, основанных на оценке стоимости, в сравнении с результатами преобразований, основанных на эвристиках. 2.2.2. Слияние представлений c группировкой и устранением дубликатов
Слияние представлений с группировкой2
(Group-by View Merging, group-by pull-up) позволяет слить представление, содержащее операцию
Q11
SELECT e1.employee_name, j.job_title
FROM employees e1, job_history j,
employees e2
WHERE e1.emp_id = j.emp_id and
j.start_date > '19980101' and
e2.dept_id = e1.dept_id and
e1_dept_id IN
(SELECT dept_id
FROM departaments d, locations l
WHERE d.loc_id = l.loc_id and
l.country_id = 'US')
GROUP BY e2.dept_id, e1.emp_id, j.rowid,
e1.employee_name, j.job_title,
e1.salary
HAVING e1.salary > AVG (e2.salary);
В непреобразованном запросе Q10 требуется, чтобы агрегация выполнялась на всей таблице 2.2.3. Проталкивание предикатов соединенияВ этом преобразовании (Join Predicate Pushdown) предикаты соединения проталкиваются внутрь представления. Проталкиваемые предикаты соединения, оказавшись внутри представления, действуют подобно корреляции, тем самым, делая доступными новые пути доступа. Проталкивание предикатов соединения позволяет соединять представление с внешними таблицами методом вложенных циклов на основе индексного доступа, недоступного обычным представлениям, которые могут соединяться только методами хэш-соединения или сортировки-слияния. Преобразование накладывает такой частичный порядок на соединяемые таблицы, что таблицы, к которым присоединяется представление (посредством проталкиваемых предикатов), должны предшествовать представлению, а представление должно соединяться методом вложенных циклов.
В качестве дополнительной оптимизации после проталкивания предикатов соединения может удаляться операция Рассмотрим следующий запрос, возвращающий информацию о сотрудниках и их истории работы (job history) для сотрудников (employees), которые работают в отделениях (departaments), расположенных в Великобритании (U.K.) или США (U.S.):
Q12
SELECT e1.employee_name, j.job_title,
e2.employee_name as mgr_name
FROM employees e1, job_history j,
employees e2,
(SELECT DISTINCT dept_id
FROM departments d, locations l
WHERE d.loc_id = l.loc_id and
l.county_id IN ('U.K.','U.S.')) V
WHERE e1.emp_id = j.emp_id and
j.start_date > '19980101' and
e1.mgr_id = e2.emp_id and
e1.dept_id = V.dept_id;
Запрос Q12 преобразуется на основе проталкивания предиката соединения в запрос Q13. Это преобразование позволяет нам удалить из представления дорогостоящую операцию
Q13
SELECT e1.employee_name, j.job_title,
e2.employee_name as mgr_name
FROM employees e1, job_history j,
employees e2,
(SELECT dept_id
FROM departments d, locations l
WHERE d.loc_id = l.loc_id and
l.county_id IN ('U.K.','U.S.') and
e1.dept_id = d.dept_id) V
WHERE e1.emp_id = j.emp_id and
j.start_date > '19980101' and
e1.mgr_id = e2.emp_id;
В Q13 для соединения представления
В Oracle проталкивание предикатов соединения может применяться как к сливаемым (например, с 2.2.4. Размещение группировки
Преобразование "проталкивание группировки" [1], [24] (Group-By Pushdown) проталкивает операцию
Размещение группировки (Group-By Placement) также может позволить вытянуть операцию Сначала оптимизатор Oracle выполняет слияние представлений с группировками ("вытягивание группировки", Group-By Pullup), за которым далее следует преобразование "проталкивание группировки", не затрагивающее те запросы, которые подверглись слиянию представлений с группировками. Общее преобразование "размещение группировки" будет доступно в следующей версии Oracle. 2.2.5. Факторизация соединений
Факторизация соединений (Join Factorization) применяется для запросов с
Q14
SELECT e.first_name, e.last_name, job_id,
d.departament_name, l.city
FROM employees e, departaments d,
locations l
WHERE e.dept_id = d.dept_id and
d.location_id = l.location_id
UNION ALL
SELECT e.first_name, e.last_name, j.job_id,
d.departament_name, l.city
FROM employees e, job_history j,
departaments d, locations l
WHERE e.emp_id = j.emp_id and
j.dept_id = d.dept_id and
d.location_id = l.location_id;
Q15
SELECT V.first_name, V.last_name, V.job_id,
d.departament_name, l.city
FROM departaments d, locations l,
(SELECT e.first_name, e.last_name
e.job_id, e.dept_id
FROM employees e
UNION ALL
SELECT e.first_name, e.last_name
j.job_id, j.dept_id
FROM employees e, job_history j
WHERE e.emp_id = j.emp_id) V
WHERE d.dept_id = V.dept_id and
d.location_id = l.location_id;
Интересно, что имеется множество случаев, когда общие таблицы можно факторизовать, но соответствующие предикаты соединения вытянуть невозможно. В таких случаях предикаты соединения можно оставить внутри представления с 2.2.6. Вытягивание предиката
Преобразование "вытягивание предиката" (Predicate Pullup) фильтрации вытягивает дорогостоящие предикаты фильтрации из представления в запрос, содержащий это представление. В настоящее время предикат считается дорогостоящим, если он содержит процедурные функции SQL, определяемые пользователем операции или подзапросы. Преобразование "вытягивание предиката" в настоящее время принимается во внимание, только если в запросе, содержащем представление, указан предикат Рассмотрим следующий запрос, содержащий представление с двумя дорогостоящими предикатами:
Q16
SELECT *
FROM (SELECT document_id
FROM product_docs
WHERE containts(summary,'optimizer',1) > 0
AND containts(full_text,'execution',2) > 0
ORDER BY create_date) V
WHERE rownum <= 20;
Поскольку в представлении имеются два дорогостоящих предиката, существуют три способа, которыми может быть выполнено преобразование вытягивания предиката, один из которых приведен ниже:
Q17
SELECT *
FROM (SELECT document_id, value(r) as vr
FROM product_docs
WHERE containts(full_text,'execution',2) > 0
ORDER BY create_date) V
WHERE containts(summary,'optimizer',1) > 0
AND rownum <= 20;
Выполнение поздней проверки дорогостоящих предикатов на значительно сокращенном наборе данных может, в некоторых случаях, улучшить производительность запроса. Если предикаты отфильтровывают очень мало строк, то мы можем избежать выполнения дорогостоящего предиката на полном наборе данных. Сокращение объема данных происходит из-за наличия предиката 2.2.7. Преобразование операций над множествами в соединения
Операции над множествами 2.2.8. Внесение дизъюнкции в объединение
Если предикаты фильтрации или соединения появляются в дизъюнкции, запрос может быть развернут в запрос с 2 Заметим, что 3 В некоторых случаях anti-/semi-/outer-соединяемые представления могут, на самом деле, сливаться, особенно, если они содержат единственную таблицу. 4 Rownum — это конструкция Oracle, позволяющая пользователям указать максимальное количество кортежей, которые должны выдаваться запросом. |
|
CITForum © 1997–2025