SlideShare une entreprise Scribd logo
1  sur  57
СУБД
Лекция 7
Павел Щербинин
Оптимизируйте доступ к
данным
• не извлекает ли приложение больше данных, чем
нужно
• не анализирует ли сервер MySQL больше строк, чем
это необходимо
Типичные ошибки:
• Выборка ненужных строк
• Выборка всех столбцов из соединения нескольких
таблиц
• Выборка всех столбцов
Декомпозиция соединения
SELECT *
FROM tag
JOIN tag_post ON tag_post.tag_id=tag.id
JOIN post ON tag_post.post_id=post.id
WHERE tag.tag=mysql;
SELECT * FROM tag WHERE tag=mysql;
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id in
(123,456,567,9098,8904);
Декомпозиция соединения
Соединение в приложении может оказаться
эффективнее в следующих случаях:
• Организован кэш и вы повторно используете ранее
запрошенные данные
• Часто используются таблицы типа MyISAM
• Данные распределены по нескольким серверам
• Вместо соединения с большой таблицей используется
список IN()
• В соединении несколько раз встречается одна и та же
таблица
Выполнение запросов
Состояние запроса
SHOW FULL PROCESSLIST;
Sleep
Поток ожидает поступления нового запроса от клиента.
Query
Поток либо занят выполнением запроса, либо отправляет клиенту результаты.
Locked
Поток ожидает предоставления табличной блокировки на уровне сервера.
Analyzing и Statistics
Поток проверяет статистику, собранную подсистемой хранения, и
оптимизирует запрос.
Copying to tmp table [on disk]
Поток обрабатывает запрос и копирует результаты во временную таблицу.
Sorting result
Поток занят сортировкой результирующего набора.
Sending data
Пересылает данные между различными стадиями обработки запроса или
генерирует результирующий набор или возвращает результаты клиенту.
Оптимизатор запросов
SELECT SQL_NO_CACHE COUNT(*) FROM sakila.film_actor;
mysql> SHOW STATUS LIKE last_query_cost;
COUNT(*)
5462
Variable_name Value
Last_query_cost 1040.599000
Оптимизатор запросов
• Некорректная статистика.
• Принятая метрика стоимости не всегда эквивалентна истинной
стоимости выполнения запроса.
• Представление MySQL о том, что такое «оптимально», может
расходиться с вашим представлением.
• MySQL не берет в расчет другие одновременно выполняющиеся
запросы.
• MySQL не всегда выполняет оптимизацию по стоимости. Иногда он
просто следует правилам.
• Оптимизатор не учитывает стоимость операций, которые ему
неподконтрольны, например выполнение хранимых или
определенных пользователем функций.
• Не всегда оптимизатор способен рассмотреть все возможные планы
выполнения, поэтому оптимальный план он может просто не увидеть.
Оптимизатор запросов
Изменение порядка соединения
Таблицы не обязательно соединять именно в том порядке, который указан в
запросе.
Применение алгебраических правил эквивалентности
MySQL применяет алгебраические преобразования для упрощения
выражений и приведения их к каноническому виду. Она умеет так-же вычислять
константные выражения, исключая заведомо невыполнимые и всегда
выполняющиеся условия.
(5=5 AND a>5) -> a>5
(a < b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
Оптимизации COUNT(), MIN() и MAX()
Наличие индексов и сведений о возможности хранения NULL-значений в
столбцах часто позволяет вообще не вычислять эти выражения. Если применена
такая оптимизация, то в плане, выведенном командой EXPLAIN, будет
присутствовать фраза «Select tables optimized away» (некоторые таблицы
исключены при оптимизации).
Оптимизатор запросов
Вычисление и свертка константных выражений
Если MySQL обнаруживает, что выражение можно свернуть в константу, то
делает это на стадии оптимизации.
EXPLAIN SELECT film.film_id, film_actor.actor_id
FROM sakila.film
INNER JOIN sakila.film_actor USING(film_id)
WHERE film.film_id = 1;
| id | select_type | table | type | key | ref | rows |
| 1 | SIMPLE | film | const | PRIMARY | const | 1 |
| 1 | SIMPLE | film_actor | ref | idx_fk_film_id | const | 10 |
Покрывающие индексы
Если индекс содержит все необходимые запросу столбцы, то MySQL может
воспользоваться им, вообще не читая данные таблицы.
Оптимизация подзапросов
MySQL умеет преобразовывать некоторые виды подзапросов в более
эффективные эквивалентные формы, сводя их к поиску по индексу.
Оптимизатор запросов
Раннее завершение
MySQL может прекратить обработку запроса (или какой-то шаг обработки), как
только поймет, что этот запрос или шаг полностью выполнен.
EXPLAIN SELECT film.film_id FROM sakila.film WHERE film_id = -1;
| id |...| Extra |
| 1 |...| Impossible WHERE noticed after reading const tables |
Сравнение по списку IN( )
Во многих СУБД оператор IN() – не более чем синоним нескольких условий OR,
поскольку логически они эквивалентны. Но не в MySQL, здесь перечисленные в
списке IN()значения сортируются, и для работы с ним применяется быстрый
двоичный поиск.
Оптимизатор запросов
Распространение равенства
MySQL распознает ситуации, когда в некотором запросе два столбца должны
быть равны, – например, в условии JOIN, и распространяет условие WHERE на
эквивалентные столбцы.
SELECT film.film_id
FROM sakila.film
INNER JOIN sakila.film_actor USING(film_id)
WHERE film.film_id > 500;
... WHERE film.film_id > 500 AND film_actor.film_id > 500
Соединения (JOIN) в MySQL
SELECT tbl1.col1, tbl2.col2
FROM tbl1 INNER JOIN tbl2 USING(col3)
WHERE tbl1.col1 IN(5,6);
outer_iter = iterator over tbl1 where col1 IN(5,6)
outer_row = outer_iter.next
while outer_row
inner_iter = iterator over tbl2 where col3 = outer_row.col3
inner_row = inner_iter.next
while inner_row
output [ outer_row.col1, inner_row.col2 ]
inner_row = inner_iter.next
end
outer_row = outer_iter.next
end
Соединения (JOIN) в MySQL
SELECT tbl1.col1, tbl2.col2 FROM tbl1
LEFT OUTER JOIN tbl2 USING(col3) WHERE tbl1.col1 IN(5,6);
outer_iter = iterator over tbl1 where col1 IN(5,6)
outer_row = outer_iter.next
while outer_row
inner_iter = iterator over tbl2 where col3 = outer_row.col3
inner_row = inner_iter.next
if inner_row
while inner_row
output [ outer_row.col1, inner_row.col2 ]
inner_row = inner_iter.next
end
else
output [ outer_row.col1, NULL ]
end
outer_row = outer_iter.next
end
Соединения (JOIN) в MySQL
План выполнения
Оптимизатор сортировки
• Двухпроходный (старый)
Читает указатели на строки и столбцы, упомянутые во фразе
ORDER BY, сортирует их, затем проходит по отсортированному
списку и снова читает исходные строки, чтобы вывести
результат.
• Однопроходный (новый)
Читает все необходимые запросу столбцы, сортирует строки по
столбцам, упомянутым во фразе ORDER BY, проходит по
отсортированному списку и выводит заданные столбцы.
Следовательно, в буфер сортировки поместится меньше строк и
надо будет выполнить больше циклов слияния.
Коррелированные подзапросы
SELECT * FROM sakila.film
WHERE film_id IN(
SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
Коррелированные подзапросы
SELECT * FROM sakila.film
WHERE film_id IN(
SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
SELECT GROUP_CONCAT(film_id)
FROM sakila.film_actor
WHERE actor_id = 1;
-- Result:
1,23,25,106,140,166,277,361,438,499,506,509,605,635,749
,832,939,970,980
SELECT * FROM sakila.film
WHERE film_id
IN(1,23,25,106,140,166,277,361,438,499,506,509,605,635,
749,832,939,970,980);
Коррелированные подзапросы
SELECT * FROM sakila.film
WHERE film_id IN(
SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
SELECT * FROM sakila.film
WHERE EXISTS (
SELECT * FROM sakila.film_actor WHERE actor_id = 1
AND film_actor.film_id = film.film_id);
Слияние индексов
SELECT film_id, actor_id FROM sakila.film_actor
WHERE actor_id = 1 OR film_id = 1;
Слияние индексов
SELECT film_id, actor_id FROM sakila.film_actor
WHERE actor_id = 1 OR film_id = 1;
SELECT film_id, actor_id FROM sakila.film_actor
WHERE actor_id = 1
UNION ALL
SELECT film_id, actor_id FROM sakila.film_actor
WHERE film_id = 1 AND actor_id <> 1;
Непоследовательный просмотр
индексов
SELECT ... FROM tbl WHERE b BETWEEN 2 AND 3;
Непоследовательный просмотр
индексов
SELECT ... FROM tbl WHERE b BETWEEN 2 AND 3;
Непоследовательный просмотр
индексов
EXPLAIN SELECT actor_id, MAX(film_id)
FROM sakila.film_actor
GROUP BY actor_idG
********************* 1. row **************************
id: 1
select_type: SIMPLE
table: film_actor
type: range
possible_keys: NULL
key: PRIMARY
key_len: 2
Ограничения оптимизатора MySQL 241
ref: NULL
rows: 396
Extra: Using index for group-by
Непоследовательный просмотр
индексов
SELECT MIN(actor_id) FROM sakila.actor
WHERE first_name = PENELOPE;
Непоследовательный просмотр
индексов
SELECT MIN(actor_id) FROM sakila.actor
WHERE first_name = PENELOPE;
SELECT actor_id FROM sakila.actor USE INDEX(PRIMARY)
WHERE first_name = PENELOPE LIMIT 1;
SELECT & UPDATE
UPDATE tbl AS outer_tbl
SET cnt = (
SELECT count(*) FROM tbl AS inner_tbl
WHERE inner_tbl.type = outer_tbl.type
);
SELECT & UPDATE
UPDATE tbl AS outer_tbl
SET cnt = (
SELECT count(*) FROM tbl AS inner_tbl
WHERE inner_tbl.type = outer_tbl.type
);
ERROR 1093 (HY000): You can’t specify target table
‘outer_tbl’ for update in FROM clause
SELECT & UPDATE
UPDATE tbl AS outer_tbl
SET cnt = (
SELECT count(*) FROM tbl AS inner_tbl
WHERE inner_tbl.type = outer_tbl.type
);
ERROR 1093 (HY000): You can’t specify target table
‘outer_tbl’ for update in FROM clause
UPDATE tbl
INNER JOIN(
SELECT type, count(*) AS cnt
FROM tbl
GROUP BY type
) AS der USING(type)
SET tbl.cnt = der.cnt;
Что делает COUNT()
COUNT() – это особая функция, которая решает две очень
разные задачи: подсчитывает значения и строки.
Значение – это выражение, отличное от NULL.
COUNT(*) просто подсчитывает количество строк в
результирующем наборе.
Если вы хотите знать, сколько строк в результирующем наборе,
всегда употребляйте COUNT(*).
МИФЫ:
Для таблиц типа MyISAM запросы, содержащие функцию
COUNT(), выполняются очень быстро.
Оптимизация COUNT()
SELECT COUNT(*) FROM world.City WHERE ID > 5;
Оптимизация COUNT()
SELECT COUNT(*) FROM world.City WHERE ID > 5;
SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*)
FROM world.City WHERE ID <= 5;
Оптимизация COUNT()
SELECT COUNT(*) FROM world.City WHERE ID > 5;
SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*)
FROM world.City WHERE ID <= 5;
SELECT COUNT(color= blue OR color= red) FROM items;
SELECT COUNT(*) FROM items
WHERE color= blue AND color= red;
Оптимизация COUNT()
SELECT COUNT(*) FROM world.City WHERE ID > 5;
SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*)
FROM world.City WHERE ID <= 5;
SELECT COUNT(color= blue OR color= red) FROM items;
SELECT COUNT(*) FROM items
WHERE color= blue AND color= red;
SELECT SUM(IF(color = blue, 1, 0)) AS blue,
SUM(IF(color = red, 1, 0)) -> AS red FROM items;
Оптимизация COUNT()
SELECT COUNT(*) FROM world.City WHERE ID > 5;
SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*)
FROM world.City WHERE ID <= 5;
SELECT COUNT(color= blue OR color= red) FROM items;
SELECT COUNT(*) FROM items
WHERE color= blue AND color= red;
SELECT SUM(IF(color = blue, 1, 0)) AS blue,
SUM(IF(color = red, 1, 0)) AS red FROM items;
SELECT COUNT(color = blue OR NULL) AS blue, COUNT(color
= red OR NULL) AS red FROM items;
Оптимизация запросов с JOIN
• Стройте индексы по столбцам, используемым во фразах ON
или USING.
• При добавлении индексов учитывайте порядок соединения.
В общем случае следует индексировать только вторую
таблицу в порядке соединения, если, конечно, индекс не
нужен для каких-то других целей.
• Старайтесь, чтобы в выражениях GROUP BY и ORDER BY
встречались столбцы только из одной таблицы, тогда у MySQL
появится возможность воспользоваться для этой операции
индексом.
• Будьте внимательны при переходе на новую версию MySQL,
поскольку в разные моменты изменялись синтаксис
соединения, приоритеты операторов и другие аспекты
поведения.
Оптимизация GROUP BY и
DISTINCT
SELECT actor.first_name, actor.last_name, COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY actor.first_name, actor.last_name;
Оптимизация GROUP BY и
DISTINCT
SELECT actor.first_name, actor.last_name, COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY actor.first_name, actor.last_name;
SELECT actor.first_name, actor.last_name, COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY film_actor.actor_id;
Оптимизация GROUP BY и
DISTINCT
SELECT actor.first_name, actor.last_name, COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY actor.first_name, actor.last_name;
SELECT MIN(actor.first_name), MAX(actor.last_name),
COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY film_actor.actor_id;
Оптимизация GROUP BY и
DISTINCT
SELECT actor.first_name, actor.last_name, COUNT(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY actor.first_name, actor.last_name;
SELECT actor.first_name, actor.last_name, c.cnt
FROM sakila.actor
INNER JOIN (
SELECT actor_id, COUNT(*) AS cnt
FROM sakila.film_actor
GROUP BY actor_id
) AS c USING(actor_id) ;
Оптимизация LIMIT со
смещением
SELECT film_id, description
FROM sakila.film
ORDER BY title
LIMIT 50, 5;
Оптимизация LIMIT со
смещением
SELECT film_id, description
FROM sakila.film
ORDER BY title
LIMIT 50, 5;
SELECT film.film_id, film.description
FROM sakila.film
INNER JOIN (
SELECT film_id FROM sakila.film
ORDER BY title LIMIT 50, 5
) AS lim USING(film_id);
Оптимизация LIMIT со
смещением
SELECT film_id, description
FROM sakila.film
ORDER BY title
LIMIT 50, 5;
SELECT film.film_id, film.description
FROM sakila.film
INNER JOIN (
SELECT film_id FROM sakila.film
ORDER BY title LIMIT 50, 5
) AS lim USING(film_id);
SELECT film_id, description FROM sakila.film
WHERE position BETWEEN 50 AND 54 ORDER BY position;
SQL_CALC_FOUND_ROWS
SELECT SQL_CALC_FOUND_ROWS film_id, description
FROM sakila.film
ORDER BY title
LIMIT 50, 5;
Кэш запросов
• Перед началом обработки запроса на чтение нужно
проверить, есть ли он в кэше
• Если запрос допускает кэширование, но еще не помещен в
кэш, то нужно потратить некоторое время на запись в кэш
сгенерированных результатов
• Наконец, при обработке любого запроса на запись
необходимо сделать недействительными все записи в кэше,
в которых встречается измененная таблица
Кэш запросов
Кэш запросов
Объединенные таблицы и
секционирование
Позволяют:
• Отделить статические данные от изменяющихся
• Воспользоваться физической близостью взаимосвязанных
данных для оптимизации запросов
• Проектировать таблицы так, чтобы запрос обращался к
возможно меньшему объему данных
• Упростить обслуживание очень больших наборов данных (в
этом вопросе объединенные таблицы обладают некоторыми
преимуществами по сравнению с секционированными)
Объединенные таблицы
CREATE TABLE t1(a INT NOT NULL PRIMARY KEY)
ENGINE=MyISAM;
CREATE TABLE t2(a INT NOT NULL PRIMARY KEY)
ENGINE=MyISAM;
INSERT INTO t1(a) VALUES(1),(2);
INSERT INTO t2(a) VALUES(1),(2);
CREATE TABLE mrg(a INT NOT NULL PRIMARY KEY)
ENGINE=MERGE UNION=(t1, t2) INSERT_METHOD=LAST;
SELECT a FROM mrg;
| a |
| 1 |
| 1 |
| 2 |
| 2 |
Объединенные таблицы
• Для объединенной таблицы необходимо больше открытых файловых
дескрипторов, чем для обычной таблицы, содержащей те же данные.
• Команда CREATE, которая создает объединенную таблицу, не проверяет,
совместимы ли ее составляющие. Если определения объединяемых
таблиц слегка различаются, то MySQL может создать объединенную
таблицу, которой впоследствии не сумеет воспользоваться.
• Запросы, обращенные к объединенной таблице, переадресуются к
каждой из составляющих таблиц. В результате поиск единственной
строки может оказаться медленнее по сравнению с поиском в одной
таблице.
• Сканирование выполняется для объединенной таблицы так же быстро,
как для обычной
• Поиск по уникальному и первичному ключу прекращается, как только
искомая строка найдена.
• Составляющие таблицы читаются в порядке, указанном в команде
CREATE TABLE.
Секционирование
CREATE TABLE orders_range (
customer_surname VARCHAR(30),
store_id INT,
salesperson_id INT,
order_date DATE,
note VARCHAR(500)
) ENGINE = MYISAM
PARTITION BY RANGE( YEAR(order_date) ) (
PARTITION p_old VALUES LESS THAN(2008),
PARTITION p_2008 VALUES LESS THAN(2009),
PARTITION p_2009 VALUES LESS THAN(MAXVALUE)
);
Секционирование
RANGE
По диапазону значений
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION p3 VALUES LESS THAN (30)
);
Секционирование
LIST
По точному списку значений
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20)
)
Секционирование
KEY
Почти то же самое что и HASH, но по ключу.
PARTITION BY KEY(s1)
PARTITIONS 10;
Секционирование
• Все секции должны управляться одной и той же подсистемой
хранения. Например, нельзя сжать только часть секций, хотя для
составляющих объединенной таблицы это допустимо.
• Любой уникальный индекс над секционированной таблицей
должен содержать столбцы, на которые ссылается функция
секционирования.
• Хотя сервер MySQL может обойтись без доступа к каждой секции
при обработке запроса к секционированной таблице, он тем
менее ставит блокировки на все секции.
• Существует ряд ограничений на функции и выражения, которые
можно использовать в механизме секционирования.
• Некоторые подсистемы хранения вообще не поддерживают
секционирование.
• Внешние ключи не работают.
Спасибо за внимание
Павел Щербинин
p.scherbinin@corp.mail.ru

Contenu connexe

Tendances

Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuning
collabock
 
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Badoo Development
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
Ontico
 
СУБД осень 2012 лекция 9
СУБД осень 2012 лекция 9СУБД осень 2012 лекция 9
СУБД осень 2012 лекция 9
Technopark
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3
Technopark
 
бд шпора2
бд шпора2бд шпора2
бд шпора2
elgin690
 
Web осень 2013 лекция 9
Web осень 2013 лекция 9Web осень 2013 лекция 9
Web осень 2013 лекция 9
Technopark
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
 
поиск узких мест в производительности My sql ботанический определитель. г. ру...
поиск узких мест в производительности My sql ботанический определитель. г. ру...поиск узких мест в производительности My sql ботанический определитель. г. ру...
поиск узких мест в производительности My sql ботанический определитель. г. ру...
rit2011
 

Tendances (19)

Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглитьСергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 
Firebird 2.5 - вектор дальнейшего развития, Dmitry Yemanov, (in Russian)
Firebird 2.5 - вектор дальнейшего развития, Dmitry Yemanov, (in Russian)Firebird 2.5 - вектор дальнейшего развития, Dmitry Yemanov, (in Russian)
Firebird 2.5 - вектор дальнейшего развития, Dmitry Yemanov, (in Russian)
 
MySQL Optimization. Russian
MySQL Optimization. RussianMySQL Optimization. Russian
MySQL Optimization. Russian
 
Новые возможности языка SQL в Firebird 3.0
Новые возможности языка SQL в Firebird 3.0Новые возможности языка SQL в Firebird 3.0
Новые возможности языка SQL в Firebird 3.0
 
Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuning
 
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
 
My sql 5.6-new-stable-mmug
My sql 5.6-new-stable-mmugMy sql 5.6-new-stable-mmug
My sql 5.6-new-stable-mmug
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeper
 
MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.
 
Введение в отладку производительности MySQL приложений
Введение в отладку производительности MySQL приложенийВведение в отладку производительности MySQL приложений
Введение в отладку производительности MySQL приложений
 
СУБД осень 2012 лекция 9
СУБД осень 2012 лекция 9СУБД осень 2012 лекция 9
СУБД осень 2012 лекция 9
 
InterBase XE7: Применение Change Views для синхронизации данных
InterBase XE7: Применение Change Views для синхронизации данныхInterBase XE7: Применение Change Views для синхронизации данных
InterBase XE7: Применение Change Views для синхронизации данных
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3
 
бд шпора2
бд шпора2бд шпора2
бд шпора2
 
Бессигнатурное обнаружение PHP-бэкдоров
Бессигнатурное обнаружение PHP-бэкдоровБессигнатурное обнаружение PHP-бэкдоров
Бессигнатурное обнаружение PHP-бэкдоров
 
Web осень 2013 лекция 9
Web осень 2013 лекция 9Web осень 2013 лекция 9
Web осень 2013 лекция 9
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
поиск узких мест в производительности My sql ботанический определитель. г. ру...
поиск узких мест в производительности My sql ботанический определитель. г. ру...поиск узких мест в производительности My sql ботанический определитель. г. ру...
поиск узких мест в производительности My sql ботанический определитель. г. ру...
 

En vedette

Тестирование весна 2014 смешанное занятие 3
Тестирование весна 2014 смешанное занятие 3Тестирование весна 2014 смешанное занятие 3
Тестирование весна 2014 смешанное занятие 3
Technopark
 
Бизнес весна 2014 лекция 6
Бизнес весна 2014 лекция 6Бизнес весна 2014 лекция 6
Бизнес весна 2014 лекция 6
Technopark
 
Проектирование интерфейсов весна 2014 занятие 7
Проектирование интерфейсов весна 2014 занятие 7Проектирование интерфейсов весна 2014 занятие 7
Проектирование интерфейсов весна 2014 занятие 7
Technopark
 
Бизнес весна 2014 лекция 4
Бизнес весна 2014 лекция 4Бизнес весна 2014 лекция 4
Бизнес весна 2014 лекция 4
Technopark
 
HighLoad весна 2014 лекция 1
HighLoad весна 2014 лекция 1HighLoad весна 2014 лекция 1
HighLoad весна 2014 лекция 1
Technopark
 

En vedette (20)

Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель Pregel
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARN
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduce
 
Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.Ru
 
СУБД 2013 Лекция №2 "Модификация данных. Выборка данных (начало)"
СУБД 2013 Лекция №2 "Модификация данных. Выборка данных (начало)"СУБД 2013 Лекция №2 "Модификация данных. Выборка данных (начало)"
СУБД 2013 Лекция №2 "Модификация данных. Выборка данных (начало)"
 
Тестирование весна 2014 смешанное занятие 3
Тестирование весна 2014 смешанное занятие 3Тестирование весна 2014 смешанное занятие 3
Тестирование весна 2014 смешанное занятие 3
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы Hadoop
 
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
 
Бизнес весна 2014 лекция 6
Бизнес весна 2014 лекция 6Бизнес весна 2014 лекция 6
Бизнес весна 2014 лекция 6
 
Проектирование интерфейсов весна 2014 занятие 7
Проектирование интерфейсов весна 2014 занятие 7Проектирование интерфейсов весна 2014 занятие 7
Проектирование интерфейсов весна 2014 занятие 7
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
 
Бизнес весна 2014 лекция 4
Бизнес весна 2014 лекция 4Бизнес весна 2014 лекция 4
Бизнес весна 2014 лекция 4
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFS
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)
 
СУБД 2013 Лекция №1 "Введение и начало проектирования"
СУБД 2013 Лекция №1 "Введение и начало проектирования"СУБД 2013 Лекция №1 "Введение и начало проектирования"
СУБД 2013 Лекция №1 "Введение и начало проектирования"
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и Hive
 
HighLoad весна 2014 лекция 1
HighLoad весна 2014 лекция 1HighLoad весна 2014 лекция 1
HighLoad весна 2014 лекция 1
 

Similaire à СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"

Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Ontico
 
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaСовременному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Sveta Smirnova
 
Оптимизации скорости выполнения запросов
Оптимизации скорости выполнения запросовОптимизации скорости выполнения запросов
Оптимизации скорости выполнения запросов
Alex.Kolonitsky
 
Разработка баз данных - введение
Разработка баз данных - введениеРазработка баз данных - введение
Разработка баз данных - введение
Александр Шамрай
 
лабораторная работа 8
лабораторная работа 8лабораторная работа 8
лабораторная работа 8
student_kai
 
физическая структура хранения артемов Ready
физическая структура хранения артемов Readyфизическая структура хранения артемов Ready
физическая структура хранения артемов Ready
rit2010
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 То, что вы хотели знать о HandlerSocket, но не смогли нагуглить То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Sergey Xek
 
MySQL для высоконагруженных проектов
MySQL для высоконагруженных проектовMySQL для высоконагруженных проектов
MySQL для высоконагруженных проектов
Softline
 
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
Ontico
 
0042
00420042
0042
JIuc
 
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
#RuPostgresLive 4: как писать и читать сложные SQL-запросы#RuPostgresLive 4: как писать и читать сложные SQL-запросы
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
Nikolay Samokhvalov
 
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQLCodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest
 
0045
00450045
0045
JIuc
 
Cергей Голубчик, Monty Program AB
Cергей Голубчик, Monty Program ABCергей Голубчик, Monty Program AB
Cергей Голубчик, Monty Program AB
Ontico
 

Similaire à СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование" (20)

Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
 
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaСовременному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
Современному хайлоду - современные решения: MySQL 8.0 и улучшения Percona
 
Оптимизации скорости выполнения запросов
Оптимизации скорости выполнения запросовОптимизации скорости выполнения запросов
Оптимизации скорости выполнения запросов
 
My sql 0
My sql 0My sql 0
My sql 0
 
Troubleshooting my sql_performance_addons
Troubleshooting my sql_performance_addonsTroubleshooting my sql_performance_addons
Troubleshooting my sql_performance_addons
 
Разработка баз данных - введение
Разработка баз данных - введениеРазработка баз данных - введение
Разработка баз данных - введение
 
лабораторная работа 8
лабораторная работа 8лабораторная работа 8
лабораторная работа 8
 
физическая структура хранения артемов Ready
физическая структура хранения артемов Readyфизическая структура хранения артемов Ready
физическая структура хранения артемов Ready
 
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 То, что вы хотели знать о HandlerSocket, но не смогли нагуглить То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
 
MySQL для высоконагруженных проектов
MySQL для высоконагруженных проектовMySQL для высоконагруженных проектов
MySQL для высоконагруженных проектов
 
34 - Базы данных. Рекомендации по составлению запросов
34 - Базы данных. Рекомендации по составлению запросов34 - Базы данных. Рекомендации по составлению запросов
34 - Базы данных. Рекомендации по составлению запросов
 
Базы данных лекция №8
Базы данных лекция №8Базы данных лекция №8
Базы данных лекция №8
 
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
Олег Бартунов, Федор Сигаев, Александр Коротков (PostgreSQL)
 
0042
00420042
0042
 
Как читать и интерпретировать вывод команды EXPLAIN
Как читать и интерпретировать вывод команды EXPLAINКак читать и интерпретировать вывод команды EXPLAIN
Как читать и интерпретировать вывод команды EXPLAIN
 
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
#RuPostgresLive 4: как писать и читать сложные SQL-запросы#RuPostgresLive 4: как писать и читать сложные SQL-запросы
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
 
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQLCodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
 
0045
00450045
0045
 
24 25 запросы
24 25 запросы24 25 запросы
24 25 запросы
 
Cергей Голубчик, Monty Program AB
Cергей Голубчик, Monty Program ABCергей Голубчик, Monty Program AB
Cергей Голубчик, Monty Program AB
 

Plus de Technopark

Plus de Technopark (9)

Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
 
Java осень 2014 занятие 7
Java осень 2014 занятие 7Java осень 2014 занятие 7
Java осень 2014 занятие 7
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5
 
Java осень 2014 занятие 3
Java осень 2014 занятие 3Java осень 2014 занятие 3
Java осень 2014 занятие 3
 
Java осень 2014 занятие 1
Java осень 2014 занятие 1Java осень 2014 занятие 1
Java осень 2014 занятие 1
 
Java осень 2014 занятие 2
Java осень 2014 занятие 2Java осень 2014 занятие 2
Java осень 2014 занятие 2
 

СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"

  • 2. Оптимизируйте доступ к данным • не извлекает ли приложение больше данных, чем нужно • не анализирует ли сервер MySQL больше строк, чем это необходимо Типичные ошибки: • Выборка ненужных строк • Выборка всех столбцов из соединения нескольких таблиц • Выборка всех столбцов
  • 3. Декомпозиция соединения SELECT * FROM tag JOIN tag_post ON tag_post.tag_id=tag.id JOIN post ON tag_post.post_id=post.id WHERE tag.tag=mysql; SELECT * FROM tag WHERE tag=mysql; SELECT * FROM tag_post WHERE tag_id=1234; SELECT * FROM post WHERE post.id in (123,456,567,9098,8904);
  • 4. Декомпозиция соединения Соединение в приложении может оказаться эффективнее в следующих случаях: • Организован кэш и вы повторно используете ранее запрошенные данные • Часто используются таблицы типа MyISAM • Данные распределены по нескольким серверам • Вместо соединения с большой таблицей используется список IN() • В соединении несколько раз встречается одна и та же таблица
  • 6. Состояние запроса SHOW FULL PROCESSLIST; Sleep Поток ожидает поступления нового запроса от клиента. Query Поток либо занят выполнением запроса, либо отправляет клиенту результаты. Locked Поток ожидает предоставления табличной блокировки на уровне сервера. Analyzing и Statistics Поток проверяет статистику, собранную подсистемой хранения, и оптимизирует запрос. Copying to tmp table [on disk] Поток обрабатывает запрос и копирует результаты во временную таблицу. Sorting result Поток занят сортировкой результирующего набора. Sending data Пересылает данные между различными стадиями обработки запроса или генерирует результирующий набор или возвращает результаты клиенту.
  • 7. Оптимизатор запросов SELECT SQL_NO_CACHE COUNT(*) FROM sakila.film_actor; mysql> SHOW STATUS LIKE last_query_cost; COUNT(*) 5462 Variable_name Value Last_query_cost 1040.599000
  • 8. Оптимизатор запросов • Некорректная статистика. • Принятая метрика стоимости не всегда эквивалентна истинной стоимости выполнения запроса. • Представление MySQL о том, что такое «оптимально», может расходиться с вашим представлением. • MySQL не берет в расчет другие одновременно выполняющиеся запросы. • MySQL не всегда выполняет оптимизацию по стоимости. Иногда он просто следует правилам. • Оптимизатор не учитывает стоимость операций, которые ему неподконтрольны, например выполнение хранимых или определенных пользователем функций. • Не всегда оптимизатор способен рассмотреть все возможные планы выполнения, поэтому оптимальный план он может просто не увидеть.
  • 9. Оптимизатор запросов Изменение порядка соединения Таблицы не обязательно соединять именно в том порядке, который указан в запросе. Применение алгебраических правил эквивалентности MySQL применяет алгебраические преобразования для упрощения выражений и приведения их к каноническому виду. Она умеет так-же вычислять константные выражения, исключая заведомо невыполнимые и всегда выполняющиеся условия. (5=5 AND a>5) -> a>5 (a < b AND b=c) AND a=5 -> b>5 AND b=c AND a=5 Оптимизации COUNT(), MIN() и MAX() Наличие индексов и сведений о возможности хранения NULL-значений в столбцах часто позволяет вообще не вычислять эти выражения. Если применена такая оптимизация, то в плане, выведенном командой EXPLAIN, будет присутствовать фраза «Select tables optimized away» (некоторые таблицы исключены при оптимизации).
  • 10. Оптимизатор запросов Вычисление и свертка константных выражений Если MySQL обнаруживает, что выражение можно свернуть в константу, то делает это на стадии оптимизации. EXPLAIN SELECT film.film_id, film_actor.actor_id FROM sakila.film INNER JOIN sakila.film_actor USING(film_id) WHERE film.film_id = 1; | id | select_type | table | type | key | ref | rows | | 1 | SIMPLE | film | const | PRIMARY | const | 1 | | 1 | SIMPLE | film_actor | ref | idx_fk_film_id | const | 10 | Покрывающие индексы Если индекс содержит все необходимые запросу столбцы, то MySQL может воспользоваться им, вообще не читая данные таблицы. Оптимизация подзапросов MySQL умеет преобразовывать некоторые виды подзапросов в более эффективные эквивалентные формы, сводя их к поиску по индексу.
  • 11. Оптимизатор запросов Раннее завершение MySQL может прекратить обработку запроса (или какой-то шаг обработки), как только поймет, что этот запрос или шаг полностью выполнен. EXPLAIN SELECT film.film_id FROM sakila.film WHERE film_id = -1; | id |...| Extra | | 1 |...| Impossible WHERE noticed after reading const tables | Сравнение по списку IN( ) Во многих СУБД оператор IN() – не более чем синоним нескольких условий OR, поскольку логически они эквивалентны. Но не в MySQL, здесь перечисленные в списке IN()значения сортируются, и для работы с ним применяется быстрый двоичный поиск.
  • 12. Оптимизатор запросов Распространение равенства MySQL распознает ситуации, когда в некотором запросе два столбца должны быть равны, – например, в условии JOIN, и распространяет условие WHERE на эквивалентные столбцы. SELECT film.film_id FROM sakila.film INNER JOIN sakila.film_actor USING(film_id) WHERE film.film_id > 500; ... WHERE film.film_id > 500 AND film_actor.film_id > 500
  • 13. Соединения (JOIN) в MySQL SELECT tbl1.col1, tbl2.col2 FROM tbl1 INNER JOIN tbl2 USING(col3) WHERE tbl1.col1 IN(5,6); outer_iter = iterator over tbl1 where col1 IN(5,6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next while inner_row output [ outer_row.col1, inner_row.col2 ] inner_row = inner_iter.next end outer_row = outer_iter.next end
  • 14. Соединения (JOIN) в MySQL SELECT tbl1.col1, tbl2.col2 FROM tbl1 LEFT OUTER JOIN tbl2 USING(col3) WHERE tbl1.col1 IN(5,6); outer_iter = iterator over tbl1 where col1 IN(5,6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next if inner_row while inner_row output [ outer_row.col1, inner_row.col2 ] inner_row = inner_iter.next end else output [ outer_row.col1, NULL ] end outer_row = outer_iter.next end
  • 17. Оптимизатор сортировки • Двухпроходный (старый) Читает указатели на строки и столбцы, упомянутые во фразе ORDER BY, сортирует их, затем проходит по отсортированному списку и снова читает исходные строки, чтобы вывести результат. • Однопроходный (новый) Читает все необходимые запросу столбцы, сортирует строки по столбцам, упомянутым во фразе ORDER BY, проходит по отсортированному списку и выводит заданные столбцы. Следовательно, в буфер сортировки поместится меньше строк и надо будет выполнить больше циклов слияния.
  • 18. Коррелированные подзапросы SELECT * FROM sakila.film WHERE film_id IN( SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
  • 19. Коррелированные подзапросы SELECT * FROM sakila.film WHERE film_id IN( SELECT film_id FROM sakila.film_actor WHERE actor_id = 1); SELECT GROUP_CONCAT(film_id) FROM sakila.film_actor WHERE actor_id = 1; -- Result: 1,23,25,106,140,166,277,361,438,499,506,509,605,635,749 ,832,939,970,980 SELECT * FROM sakila.film WHERE film_id IN(1,23,25,106,140,166,277,361,438,499,506,509,605,635, 749,832,939,970,980);
  • 20. Коррелированные подзапросы SELECT * FROM sakila.film WHERE film_id IN( SELECT film_id FROM sakila.film_actor WHERE actor_id = 1); SELECT * FROM sakila.film WHERE EXISTS ( SELECT * FROM sakila.film_actor WHERE actor_id = 1 AND film_actor.film_id = film.film_id);
  • 21. Слияние индексов SELECT film_id, actor_id FROM sakila.film_actor WHERE actor_id = 1 OR film_id = 1;
  • 22. Слияние индексов SELECT film_id, actor_id FROM sakila.film_actor WHERE actor_id = 1 OR film_id = 1; SELECT film_id, actor_id FROM sakila.film_actor WHERE actor_id = 1 UNION ALL SELECT film_id, actor_id FROM sakila.film_actor WHERE film_id = 1 AND actor_id <> 1;
  • 25. Непоследовательный просмотр индексов EXPLAIN SELECT actor_id, MAX(film_id) FROM sakila.film_actor GROUP BY actor_idG ********************* 1. row ************************** id: 1 select_type: SIMPLE table: film_actor type: range possible_keys: NULL key: PRIMARY key_len: 2 Ограничения оптимизатора MySQL 241 ref: NULL rows: 396 Extra: Using index for group-by
  • 27. Непоследовательный просмотр индексов SELECT MIN(actor_id) FROM sakila.actor WHERE first_name = PENELOPE; SELECT actor_id FROM sakila.actor USE INDEX(PRIMARY) WHERE first_name = PENELOPE LIMIT 1;
  • 28. SELECT & UPDATE UPDATE tbl AS outer_tbl SET cnt = ( SELECT count(*) FROM tbl AS inner_tbl WHERE inner_tbl.type = outer_tbl.type );
  • 29. SELECT & UPDATE UPDATE tbl AS outer_tbl SET cnt = ( SELECT count(*) FROM tbl AS inner_tbl WHERE inner_tbl.type = outer_tbl.type ); ERROR 1093 (HY000): You can’t specify target table ‘outer_tbl’ for update in FROM clause
  • 30. SELECT & UPDATE UPDATE tbl AS outer_tbl SET cnt = ( SELECT count(*) FROM tbl AS inner_tbl WHERE inner_tbl.type = outer_tbl.type ); ERROR 1093 (HY000): You can’t specify target table ‘outer_tbl’ for update in FROM clause UPDATE tbl INNER JOIN( SELECT type, count(*) AS cnt FROM tbl GROUP BY type ) AS der USING(type) SET tbl.cnt = der.cnt;
  • 31. Что делает COUNT() COUNT() – это особая функция, которая решает две очень разные задачи: подсчитывает значения и строки. Значение – это выражение, отличное от NULL. COUNT(*) просто подсчитывает количество строк в результирующем наборе. Если вы хотите знать, сколько строк в результирующем наборе, всегда употребляйте COUNT(*). МИФЫ: Для таблиц типа MyISAM запросы, содержащие функцию COUNT(), выполняются очень быстро.
  • 32. Оптимизация COUNT() SELECT COUNT(*) FROM world.City WHERE ID > 5;
  • 33. Оптимизация COUNT() SELECT COUNT(*) FROM world.City WHERE ID > 5; SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5;
  • 34. Оптимизация COUNT() SELECT COUNT(*) FROM world.City WHERE ID > 5; SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5; SELECT COUNT(color= blue OR color= red) FROM items; SELECT COUNT(*) FROM items WHERE color= blue AND color= red;
  • 35. Оптимизация COUNT() SELECT COUNT(*) FROM world.City WHERE ID > 5; SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5; SELECT COUNT(color= blue OR color= red) FROM items; SELECT COUNT(*) FROM items WHERE color= blue AND color= red; SELECT SUM(IF(color = blue, 1, 0)) AS blue, SUM(IF(color = red, 1, 0)) -> AS red FROM items;
  • 36. Оптимизация COUNT() SELECT COUNT(*) FROM world.City WHERE ID > 5; SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5; SELECT COUNT(color= blue OR color= red) FROM items; SELECT COUNT(*) FROM items WHERE color= blue AND color= red; SELECT SUM(IF(color = blue, 1, 0)) AS blue, SUM(IF(color = red, 1, 0)) AS red FROM items; SELECT COUNT(color = blue OR NULL) AS blue, COUNT(color = red OR NULL) AS red FROM items;
  • 37. Оптимизация запросов с JOIN • Стройте индексы по столбцам, используемым во фразах ON или USING. • При добавлении индексов учитывайте порядок соединения. В общем случае следует индексировать только вторую таблицу в порядке соединения, если, конечно, индекс не нужен для каких-то других целей. • Старайтесь, чтобы в выражениях GROUP BY и ORDER BY встречались столбцы только из одной таблицы, тогда у MySQL появится возможность воспользоваться для этой операции индексом. • Будьте внимательны при переходе на новую версию MySQL, поскольку в разные моменты изменялись синтаксис соединения, приоритеты операторов и другие аспекты поведения.
  • 38. Оптимизация GROUP BY и DISTINCT SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY actor.first_name, actor.last_name;
  • 39. Оптимизация GROUP BY и DISTINCT SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY actor.first_name, actor.last_name; SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY film_actor.actor_id;
  • 40. Оптимизация GROUP BY и DISTINCT SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY actor.first_name, actor.last_name; SELECT MIN(actor.first_name), MAX(actor.last_name), COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY film_actor.actor_id;
  • 41. Оптимизация GROUP BY и DISTINCT SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY actor.first_name, actor.last_name; SELECT actor.first_name, actor.last_name, c.cnt FROM sakila.actor INNER JOIN ( SELECT actor_id, COUNT(*) AS cnt FROM sakila.film_actor GROUP BY actor_id ) AS c USING(actor_id) ;
  • 42. Оптимизация LIMIT со смещением SELECT film_id, description FROM sakila.film ORDER BY title LIMIT 50, 5;
  • 43. Оптимизация LIMIT со смещением SELECT film_id, description FROM sakila.film ORDER BY title LIMIT 50, 5; SELECT film.film_id, film.description FROM sakila.film INNER JOIN ( SELECT film_id FROM sakila.film ORDER BY title LIMIT 50, 5 ) AS lim USING(film_id);
  • 44. Оптимизация LIMIT со смещением SELECT film_id, description FROM sakila.film ORDER BY title LIMIT 50, 5; SELECT film.film_id, film.description FROM sakila.film INNER JOIN ( SELECT film_id FROM sakila.film ORDER BY title LIMIT 50, 5 ) AS lim USING(film_id); SELECT film_id, description FROM sakila.film WHERE position BETWEEN 50 AND 54 ORDER BY position;
  • 45. SQL_CALC_FOUND_ROWS SELECT SQL_CALC_FOUND_ROWS film_id, description FROM sakila.film ORDER BY title LIMIT 50, 5;
  • 46. Кэш запросов • Перед началом обработки запроса на чтение нужно проверить, есть ли он в кэше • Если запрос допускает кэширование, но еще не помещен в кэш, то нужно потратить некоторое время на запись в кэш сгенерированных результатов • Наконец, при обработке любого запроса на запись необходимо сделать недействительными все записи в кэше, в которых встречается измененная таблица
  • 49. Объединенные таблицы и секционирование Позволяют: • Отделить статические данные от изменяющихся • Воспользоваться физической близостью взаимосвязанных данных для оптимизации запросов • Проектировать таблицы так, чтобы запрос обращался к возможно меньшему объему данных • Упростить обслуживание очень больших наборов данных (в этом вопросе объединенные таблицы обладают некоторыми преимуществами по сравнению с секционированными)
  • 50. Объединенные таблицы CREATE TABLE t1(a INT NOT NULL PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t2(a INT NOT NULL PRIMARY KEY) ENGINE=MyISAM; INSERT INTO t1(a) VALUES(1),(2); INSERT INTO t2(a) VALUES(1),(2); CREATE TABLE mrg(a INT NOT NULL PRIMARY KEY) ENGINE=MERGE UNION=(t1, t2) INSERT_METHOD=LAST; SELECT a FROM mrg; | a | | 1 | | 1 | | 2 | | 2 |
  • 51. Объединенные таблицы • Для объединенной таблицы необходимо больше открытых файловых дескрипторов, чем для обычной таблицы, содержащей те же данные. • Команда CREATE, которая создает объединенную таблицу, не проверяет, совместимы ли ее составляющие. Если определения объединяемых таблиц слегка различаются, то MySQL может создать объединенную таблицу, которой впоследствии не сумеет воспользоваться. • Запросы, обращенные к объединенной таблице, переадресуются к каждой из составляющих таблиц. В результате поиск единственной строки может оказаться медленнее по сравнению с поиском в одной таблице. • Сканирование выполняется для объединенной таблицы так же быстро, как для обычной • Поиск по уникальному и первичному ключу прекращается, как только искомая строка найдена. • Составляющие таблицы читаются в порядке, указанном в команде CREATE TABLE.
  • 52. Секционирование CREATE TABLE orders_range ( customer_surname VARCHAR(30), store_id INT, salesperson_id INT, order_date DATE, note VARCHAR(500) ) ENGINE = MYISAM PARTITION BY RANGE( YEAR(order_date) ) ( PARTITION p_old VALUES LESS THAN(2008), PARTITION p_2008 VALUES LESS THAN(2009), PARTITION p_2009 VALUES LESS THAN(MAXVALUE) );
  • 53. Секционирование RANGE По диапазону значений PARTITION BY RANGE (store_id) ( PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p3 VALUES LESS THAN (30) );
  • 54. Секционирование LIST По точному списку значений PARTITION BY LIST(store_id) ( PARTITION pNorth VALUES IN (3,5,6,9,17), PARTITION pEast VALUES IN (1,2,10,11,19,20) )
  • 55. Секционирование KEY Почти то же самое что и HASH, но по ключу. PARTITION BY KEY(s1) PARTITIONS 10;
  • 56. Секционирование • Все секции должны управляться одной и той же подсистемой хранения. Например, нельзя сжать только часть секций, хотя для составляющих объединенной таблицы это допустимо. • Любой уникальный индекс над секционированной таблицей должен содержать столбцы, на которые ссылается функция секционирования. • Хотя сервер MySQL может обойтись без доступа к каждой секции при обработке запроса к секционированной таблице, он тем менее ставит блокировки на все секции. • Существует ряд ограничений на функции и выражения, которые можно использовать в механизме секционирования. • Некоторые подсистемы хранения вообще не поддерживают секционирование. • Внешние ключи не работают.
  • 57. Спасибо за внимание Павел Щербинин p.scherbinin@corp.mail.ru