Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Базы данных. Лекции по курсу. В 4 частях. Ч.1. Учебное пособие
.pdf
Сведения о плане выполнения запроса могут быть доступны разработчику, и анализ сгенерированного СУБД плана выполнения запроса
позволяет:
понять, как СУБД будет исполнять запрос;
найти «узкие» места в запросе, максимально влияющие на время
его выполнения.
Для получения плана выполнения запроса можно использовать
SQL-операторы
explain QUERY_TEXT
explain analyze QUERY_TEXT
или
или воспользоваться клавишами «F7» или «Shift+F7».
SQL-запрос для получения плана выполнения исходного запроса
(рис. 5):
EXPLAIN ANALYZE
select p.country, count (*) books_count
from books b, publishers p
where b.publisher_id = p.id and b.genre = 'Жанр 45'
group by p.country order by 2 desc
Рис. 5. План выполнения SQL-запроса
41

Из рис. 5 видно, что стоимость плана запроса в некоторых абстрактных единицах составляет 42 978, а время выполнения запроса
~625 мс. На рис. 6 схематично показаны операции, выполняемые при
реализации запроса: чтение исходных таблиц, соединение, вычисление
агрегированных значений и сортировка.
Рис. 6. Операции при выполнении SQL-запроса
Как можно оптимизировать этот запрос?
1. Использование индексирования. Индекс – объект базы данных,
создаваемый с целью повышения скорости поиска данных. Подробно
об этом будет рассказано в теме «Физическое проектирование». Индекс позволяет искать строки, удовлетворяющие заданному критерию
поиска.
Создадим индекс для столбца
genre таблицы books:
create index on books (genre).
План выполнения SQL-запроса после создания индекса показан на
рис. 7. Из него видно, что стоимость плана запроса уменьшилась до
6729 единиц, а время выполнения запроса сократилось в 40 раз, до
13.6 мс.
На рис. 8 схематично показаны операции, выполняемые при реализации запроса. К перечисленным ранее операциям добавилась операция индексирования, которая и обеспечила
существенное сокращение
времени выполнения запроса.
Таким образом, можно сделать вывод, что, анализируя план выполнения запроса, можно оптимизировать SQL-запрос, добившись
требуемых характеристик.
42

Рис. 7. План выполнения SQL-запроса с индексированием
Рис. 8. Операции при выполнении SQL-запроса с индексированием
2. Порядок соединения таблиц. Как отмечалось ранее, на скорость
выполнения существенно влияет порядок соединения таблиц. Перепишем SQL-запрос, изменив порядок соединения. Исходный запрос:
select p.country, count (*) books_count
from books b, publishers p
where b.publisher_id = p.id and b.genre = 'Жанр 45'
group by p.country order by 2 desc
43

Измененный запрос с новым порядком индексирования:
select p.country, sum (b.cnt) books_count
from publishers p
inner join
(select publisher_id, count (*) cnt
from books where genre = 'Жанр 45'
group by publisher_id
) b
on b.publisher_id = p.id
group by p.country order by 2 desc
План выполнения нового SQL-запроса изменился (рис. 9).
Рис. 9. План выполнения SQL-запроса с измененным порядком соединения
Из рисунка видно, что стоимость плана запроса уменьшилась (хотя
и незначительно) до 6715 единиц, а время выполнения запроса умень-
44

шилось до 10.9 мс. На рис. 10 схематично показаны операции, выполняемые при реализации нового запроса: чтение исходных таблиц, соединение, вычисление агрегированных значений и сортировка.
Рис. 10. Операции при выполнении SQL-запроса с измененным порядком
соединения
3. Фрагментация таблиц. Еще один прием – фрагментация. Пусть
нам необходимо выполнить запрос «Получить все данные о книгах,
изданных в стране "Страна 5" за заданный период, отсортировав их по
времени издания».
SQL-запрос, решающий такую задачу, может иметь вид:
select b.*
from books b, publishers p
where b.publisher_id = p.id
and b.publication_date between '2000-01-01' and '2000-12-31'
and p.country = 'Страна 5'
order by b.publication_date
План выполнения SQL-запроса показан на рис. 11, а последовательность выполняемых операция в этом плане выполнения запроса –
на рис. 12. Из рис. 11 видно, что стоимость плана запроса составляет
43 353 единиц, а время выполнения запроса 578 мс. Среди операций на
рис. 12 присутствуют операции чтения таблиц, ограничения, соединения и сортировки. Отметим, что при выполнении данного SQL-
запроса
индексирование отсутствует.
45

Рис. 11. План выполнения SQL-запроса
Рис. 12. Операции при выполнении SQL-запроса
Выполним индексирование таблиц publishers и books по ключевым
полям.
create index on publishers (country)
create index on books
(publication_date)
Индексирование изменит план выполнения SQL-запроса (рис. 13),
сделает его более оптимальным. Изменится и состав операций
(рис. 14). Все это скажется на стоимости плана выполнения запроса
(9813 единиц), и времени его выполнения (10.4 мс).
46

Рис. 13. План выполнения SQL-запроса с индексированием
Рис. 14. Операции при выполнении SQL-запроса с индексированием
Выполним горизонтальную фрагментацию таблицы books по странам, в которых издавались книги:
create table books_country_5 as
select * from books
47

where publisher_id in (select id from publishers
where country = 'Страна
5')
Аналогичные запросы выполним для стран "Страна 1", …"Страна 10".
При выполнении такой серии SQL-запросов создаются таблицы
books_country_1, …books_country_10.
Перепишем теперь SQL-запрос таким образом, чтобы он работал с
фрагментированной таблицей
books.
Исходный SQL-запрос:
select b.*
from books b, publishers p
where b.publisher_id = p.id
and b.publication_date between '2000-01-01' and '2000-12-31'
and p.country = 'Страна 5'
order by b.publication_date
SQL-запрос с фрагментированной таблицей books:
select b.* from books_country_5 b
where b.publication_date between '2000-01-01' and '2000-12-31'
order by b.publication_date
План выполнения SQL-запроса с фрагментированной таблицей
books показан на рис. 15.
Рис. 15. План выполнения SQL-запроса с фрагментированной таблицей books
48

Стоимость плана выполнения запроса составляет 4318 единиц,
время выполнения SQL-запроса – 13.1 мс. Среди операций в плане
запроса присутствуют операции чтения таблицы, ограничения и сортировки (рис. 16).
Рис. 16. Операции при выполнении SQL-запроса
с фрагментированной таблицей books
Выполним индексирование созданных таблиц и вновь построим
план выполнения запроса (рис. 17):
create index on books_country_5 (publication_date)
Рис. 17. План выполнения SQL-запроса с фрагментированной таблицей books
и индексированием
Стоимость плана уменьшилась до 956 единиц, а время выполнения
SQL-запроса сократилось до 1.1 мс. Операции в плане запроса показаны на рис. 18.
49

Рис. 18. Операции при выполнении SQL-запроса с фрагментированной
таблицей books и индексированием
Результаты оптимизации для разных вариантов SQL-запроса сведены в табл. 2.
Таблица 2
с 01.01.2000 по 31.12.2000
Типы запросов
Исходный запрос 43 353 578 мс
Исходный запрос с индексированием 9 813 10.4 мс
Запрос с фрагментацией 4 319 13.1 мс
Стоимость
плана
Время
выполнения
Запрос с фрагментацией и индексированием
957 1.1 мс
Можно говорить и о вертикальной фрагментации. Рассмотрим задачу «Вывести названия всех издательств и количество книг, изданных
в каждом из них». SQL-запрос, решающий задачу, можно записать
следующим образом:
select p.name, b.cnt
from publishers p,
(select publisher_id, count (*) cnt
from books
group by publisher_id
) b
where b.publisher_id = p.id
План выполнения SQL-запроса показан на рис. 19, а последовательность выполняемых операция в этом плане – на рис. 20.
50
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
