суббота, 14 апреля 2018 г.

Оптимизация sql запросов

Оптимизация - это всегда компромисс. Преждевременная оптимизация иногда хуже чем полное отсутствие. Но иногда лучше иметь список возможных улучшений, чтобы их проверить, чем выдумывать их.
1. Выборка по первичному ключу самая быстрая.
select id, name from client where id in (1,2,3,4)
Такой запрос самый быстрый, НО если кол-во id слишком большой получим обратны эффект. Наша задача уменьшить объем передаваемых данный как от mysql до php, так и обратно. Так что этой техникой надо пользоваться очень аккуратно.

2. Есть одна особенность связанная с сортировкой и yii1.
select id, name from client inner join (select client_id, max(created_at) as created_at from worksheet group by client_id) w on w.client_id = client.id order by w.created_at desc
Проблема в том, что для запроса select count(*) from client не нужен подзапрос  select client_id, max(created_at) as created_at from worksheet group by client_id . Он даже для выборки не нужен, потому что при наличии фильтра по client.id, подзапрос будет тормозить. Правильнее переписать запрос так
select id, name from client order by (select max(created_at) from worksheet where worksheet.client_id = client.id) desc
3. exists работает медленее чем объединение, но для фильтрации он предпочтительнее так как ведет себя более стабильнее для yii1
select id, name from client inner join worksheet on worksheet.client_id = client.id where worksheet.type = 1
такой запрос отлично можно оптимизировать добавив индексы, но он не подходит для построения списка клиентов и лучше использовать exists, пусть и с большими потерями
select id, name from client where exists(select 1 from worksheet where worksheet.client_id = client.id where worksheet.type = 1)
4. Использование функций в секции where. Запрос
select id, name from client where year(created_at) = 2018
лучше переписать так
select id, name from client where created_at between '2018-01-01 00:00:00' and '2018-12-31 23:59:59'
так можно задействовать индекс по полю created_at. С функций year такого добиться не получится. Можно конечно начать использовать вычисляемые поля и индексы по ним, но по мне это излишество


Комментариев нет:

Отправить комментарий