SlideShare a Scribd company logo
PostgreSQL: практические
примеры оптимизации
SQL-запросов
Фролков Иван
Postgres Professional
Эффективность
● Что такое «эффективный запрос»?
– Быстрый? Но как? Время? Первой строки? Всего запроса?
– Ввод-вывод? Процессор? Блокировки?
● Как мы можем сравнить эффективность?
– Время выполнения
– Количество операций ввода-вывода
Выполнение запроса
● PostgreSQL — Executor
● Можно попросить реальный план выполнения
select * from acc.ledger l where l.reference like 'IN/%'
Index Scan using ledger_pkey on ledger l (cost=0.56..8.58
rows=8879325 width=162) (actual time=0.052..2573.333 rows=8880000
loops=1)
Index Cond: ((reference >= 'IN/'::text) AND (reference <
'IN0'::text))
Filter: (reference ~~ 'IN/%'::text)
Buffers: shared hit=149021 read=168134
Planning time: 0.303 ms
Execution time: 2872.353 ms
Общий принцип
Чем меньше, тем лучше!
Данных
Индексов
Ввода-вывода
Страниц
Блокировок
Latches
Еще случаи
● uuid text — 32 байта
● uuid uuid — 16 байт
● На десятке таких колонок будет совсем интересно
Еще случаи
● uuid text — 32 байта
● uuid uuid — 16 байт
● На десятке таких колонок будет совсем интересно
● Жадничайте!
И еще
● select … from
t1 join t2 join t2
where
? in (t1.col, t2.col, t3.col)
● Такое условие можно вычислить только после соединения.
Индексы
● Все тот же принцип — чем меньше, тем лучше
– Меньше индекс
– Меньше индексов
● Иногда можно и вообще без индексов
Индексы btree
● Индекс — это отсортированная последовательность
● (usr_id)
● (usr_id, added)
– Если оба реально используются, подумайте, нужны ли оба сразу
— оптимизатор выбирает лучший индекс для запроса, а не для
всего приложения
Порядок строк в индексе
● (usr_id) — usr_id равно/больше/меньше
● (usr_id,added) — usr_id равно/больше/меньше
– usr_id равно, added равно/больше/меньше
– НЕ РАБОТАЕТ (почти) -
added равно/больше/меньше
Индексы — LIKE
● Для LIKE индекс используется для поиска по префиксу —
LIKE 'str%'
● Не работает для LIKE '%str'
● Внимание — параметры!
– Тонкий момент в PostgreSQL
Покрытие индексом
● Все колонки есть в индексе
● Меньше обращений к страницам
● Меньше ввод-вывод
● Меньше latches/buffer pin
● Больше индексов/больше индекс
Пример
create table ios(
id int primary key,
val text)
insert into ios select n, repeat('X', n%100) from
generate_series(1,1000000) as gs(n)
explain(analyze, verbose,buffers)
select count(val) from ios where id between 1 and 100000
explain(analyze, verbose,buffers)
select count(id) from ios where id between 1 and 100000
План 1
Aggregate (cost=3998.45..3998.46 rows=1 width=8)
(actual time=22.241..22.242 rows=1 loops=1)
Output: count(val)
Buffers: shared hit=816
-> Index Scan using ios_pkey on public.ios
…
Output: id, val
…
Buffers: shared hit=816
План Бэ
Aggregate (cost=3347.30..3347.31 rows=1 width=8)
(actual time=16.804..16.804 rows=1 loops=1)
Buffers: shared hit=277
-> Index Only Scan using ios_pkey on public.ios
…
Heap Fetches: 0
Buffers: shared hit=277
Сравнение при параллельном выполнении
● 8 клиентов
– Обычный доступ — 220.709118 tps
– Index-only scan - 336.434901 tps
Покрытие индексом
● PostgresPro — INCLUDING
● Покрытие индексом — предпоследний способ повысить
производительность
● Почему плохо
– На каждый запрос делать индекс — это ж сколько их будет?
– Что делать, если запрос поменялся?
Методы соединения
select * from first, second
where first.key=second.key
Методы соединения
select * from first, second
where first.key=second.key
select * from first, second
where first.key<>second.key
Методы соединения
select * from first, second
where first.key=second.key
select * from first, second
where first.key<>second.key
select * from first, second
where exists(select * from third where
third.first_key=first.key and
third.second_key=second.key)
Методы соединения
● Nested loops
– for i in first_table
● For j in second_table where second_table.i=i
проверяем условия и формируем строку
Методы соединения
● Nested loops
– for i in first_table
● For j in second_table where second_table.i=i
проверяем условия и формируем строку
● Hash join
– Строим хэш-таблицу из first_table
● for j in second_table
if key_exists(hash(second_table.j))
–проверяем условия и формируем строку
– Что делать, если таблица не помещается в память?
Методы соединения
●
Nested loops
– for i in first_table
●
For j in second_table where second_table.i=i
проверяем условия и формируем строку
● Hash join
– Строим хэш-таблицу из first_table
●
for j in second_table
if key_exists(hash(second_table.j))
–проверяем условия и формируем строку
●
Merge join
–Сливаем две отсортированных first_table & second_table
●
проверяем условия и формируем строку
Методы соединения
● Nested loops
– За
● Очень дешевый
● Очень быстрый на небольших объемах
● Не требует много памяти
● Идеален для молниеносных запросов
● Единственный умеет соединения не только по равенству
– Против
● Плохо работает для больших объемов данных
Методы соединения
● Hash join
– За
●
Не нужен индекс
● Относительно быстрый
● Может быть использован для FULL OUTER JOIN
– Против
● Любит память
● Соединение только по равенству
● Не любит много значений в колонках соединения
● Велико время получения первой строки
Методы соединения
● Merge join
– За
● Быстрый на больших и малых объемах
● Не требует много памяти
● Умеет OUTER JOIN
● Подходит для соединения более чем двух таблиц
– Против
● Требует отсортированные потоки данных, что подразумевает или индекс, или
сортировку
● Соединение только по равенству
Про Postgres
● Не умеет full outer join с соединением не по равенству
● Вот только что-то никто не жаловался :-)
Статистика
● В PostgreSQL — pg_statistics или на ее основе
представление pg_stats
● Статистика — ключевой фактор для работы оптимизатора
● Проблемы — пары-тройки-четверки колонок
● Oracle — умеет. А вот PostgreSQL — нет :-(
Типовые проблемы
● Плохая схема БД
– Объемы!
● Лишние данные
● Лишние индексы
● Отсутствие нужных индексов
● Неверные типы
– Необходимость писать сложные запросы
● Бездумное использование ОРМ
Бездумное использование ОРМ
● Вообще говоря, я его не люблю
– Но мало ли что я не люблю. А народу вот нравится
●
Типовой запрос:
– select distinct <от десятков до сотен колонок>
from table1 left outer join table2 on …
left outer join table3 on …
left outer join table4 on …
where table4.col='value'
order by table1.id
limit 100
offset 20000
ОРМ-запрос. Что тут плохо
● DISTINCT
– Если вы не можете точно сказать, зачем вы используете
DISTINCT, то у вас проблемы
ОРМ-запрос. Что тут плохо
● DISTINCT
– Если вы не можете точно сказать, зачем вы используете
DISTINCT, то у вас проблемы
● LEFT OUTER JOIN
– Бьет по рукам оптимизатору, строго задавая порядок
соединения
– Более того, условия во WHERE делают внешнее соединение
ненужным
ОРМ-запрос. Что тут плохо
● DISTINCT
– Если вы не можете точно сказать, зачем вы используете
DISTINCT, то у вас проблемы
● LEFT OUTER JOIN
– Бьет по рукам оптимизатору, строго задавая порядок соединения
– Более того, условия во WHERE делают внешнее соединение
ненужным
● LIMIT/OFFSET почти всегда плохо
Что делать?
● Четко определиться, какую бизнес-задачу решает запрос.
Возможно, после этого необходимость в нем отпадет
● Разобраться с ОРМ
– Выбирать только то, что нужно
– Постараться перейти к INNER JOIN
– Постараться избавиться от LIMIT/OFFSET
Выводы
● Чем меньше, тем лучше
● Знайте ваши данные

More Related Content

PPTX
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
PDF
NoSQL внутри SQL: приземленные вопросы практического применения / Дмитрий До...
PDF
Практика совместного использования Lua и C в opensource спам-фильтре Rspamd /...
PDF
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
PDF
Дмитрий Новиков - Tarantool в Badoo
PPTX
Поиск наизнанку
PPTX
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
PDF
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
NoSQL внутри SQL: приземленные вопросы практического применения / Дмитрий До...
Практика совместного использования Lua и C в opensource спам-фильтре Rspamd /...
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Дмитрий Новиков - Tarantool в Badoo
Поиск наизнанку
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
Linux API с точки зрения разработчика веб-сервера / Валентин Бартенев (NGINX,...

What's hot (20)

PDF
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
PDF
Осваиваем Tarantool 1.6 / Евгений Шадрин (Sberbank Digital Ventures)
PDF
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
PDF
Обзор перспективных баз данных для highload / Юрий Насретдинов
PDF
pgconf.ru 2015 avito postgresql
PDF
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
PDF
2014.09.24 история небольшого успеха с PostgreSQL (Yandex)
PDF
Последние новости постгреса с PGCon / О.Бартунов, А.Коротков, Ф.Сигаев (Postg...
PDF
Avito Stachka 2012
PDF
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
PDF
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
PDF
Современная операционная система: что надо знать разработчику / Александр Кри...
PPTX
Mysql vs postgresql
PPTX
Как ускорить MySQL Handler Socket в 9 раз / Александр Яковлев (Мамба)
PDF
SphinxSearch Meetup - Tips&tricks
PDF
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
PPTX
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
PPTX
OpenResty: превращаем NGINX в полноценный сервер приложений / Владимир Прота...
PDF
Нагруженный поиск на Sphinx
PDF
AVITO. Решардинг Redis без даунтайма. DevConf 2012
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
Осваиваем Tarantool 1.6 / Евгений Шадрин (Sberbank Digital Ventures)
Мониторинг ожиданий в PostgreSQL / Курбангалиев Ильдус (Postgres Professional)
Обзор перспективных баз данных для highload / Юрий Насретдинов
pgconf.ru 2015 avito postgresql
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
2014.09.24 история небольшого успеха с PostgreSQL (Yandex)
Последние новости постгреса с PGCon / О.Бартунов, А.Коротков, Ф.Сигаев (Postg...
Avito Stachka 2012
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
Современная операционная система: что надо знать разработчику / Александр Кри...
Mysql vs postgresql
Как ускорить MySQL Handler Socket в 9 раз / Александр Яковлев (Мамба)
SphinxSearch Meetup - Tips&tricks
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
MySQL 5.7 - NoSQL - JSON, Protocol X, Document Store / Петр Зайцев (Percona)
OpenResty: превращаем NGINX в полноценный сервер приложений / Владимир Прота...
Нагруженный поиск на Sphinx
AVITO. Решардинг Redis без даунтайма. DevConf 2012
Ad

Similar to PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Postgres Professional) (20)

PPTX
Query perfomance tuning
PDF
Народные средства оптимизации PostgreSQL
PDF
PostgreSQL performance recipes
PPTX
django-and-postgresql
PPTX
MySQL Optimization. Russian
PPTX
Оптимизации скорости выполнения запросов
PDF
Иван Фролков
PDF
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
PPTX
Big Data - первые шаги
ODP
Server optimization
PPTX
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
PDF
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
PDF
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
PPTX
Реляционные базы данных
PDF
19.10 - WebPromo SEO Day - "SEO-автоматизатор: кто он?" - Владислав Моргун
PDF
Excel in Javascript
PDF
Олег Бартунов и Иван Панченко
PDF
20120226 information retrieval raskovalov_lecture03-04
PPT
sphinx Hlpp2008
PPTX
Мастер класс по алгоритмам. Часть 1
Query perfomance tuning
Народные средства оптимизации PostgreSQL
PostgreSQL performance recipes
django-and-postgresql
MySQL Optimization. Russian
Оптимизации скорости выполнения запросов
Иван Фролков
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Big Data - первые шаги
Server optimization
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Реляционные базы данных
19.10 - WebPromo SEO Day - "SEO-автоматизатор: кто он?" - Владислав Моргун
Excel in Javascript
Олег Бартунов и Иван Панченко
20120226 information retrieval raskovalov_lecture03-04
sphinx Hlpp2008
Мастер класс по алгоритмам. Часть 1
Ad

More from Ontico (20)

PDF
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
PDF
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
PPTX
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
PDF
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
PDF
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
PDF
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PDF
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
PDF
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
PPTX
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
PPTX
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
PDF
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
PPTX
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
PPTX
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
PDF
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
PPT
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
PPTX
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
PPTX
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
PPTX
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
PPTX
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
PDF
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...

PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Postgres Professional)

  • 2. Эффективность ● Что такое «эффективный запрос»? – Быстрый? Но как? Время? Первой строки? Всего запроса? – Ввод-вывод? Процессор? Блокировки? ● Как мы можем сравнить эффективность? – Время выполнения – Количество операций ввода-вывода
  • 3. Выполнение запроса ● PostgreSQL — Executor ● Можно попросить реальный план выполнения select * from acc.ledger l where l.reference like 'IN/%' Index Scan using ledger_pkey on ledger l (cost=0.56..8.58 rows=8879325 width=162) (actual time=0.052..2573.333 rows=8880000 loops=1) Index Cond: ((reference >= 'IN/'::text) AND (reference < 'IN0'::text)) Filter: (reference ~~ 'IN/%'::text) Buffers: shared hit=149021 read=168134 Planning time: 0.303 ms Execution time: 2872.353 ms
  • 4. Общий принцип Чем меньше, тем лучше! Данных Индексов Ввода-вывода Страниц Блокировок Latches
  • 5. Еще случаи ● uuid text — 32 байта ● uuid uuid — 16 байт ● На десятке таких колонок будет совсем интересно
  • 6. Еще случаи ● uuid text — 32 байта ● uuid uuid — 16 байт ● На десятке таких колонок будет совсем интересно ● Жадничайте!
  • 7. И еще ● select … from t1 join t2 join t2 where ? in (t1.col, t2.col, t3.col) ● Такое условие можно вычислить только после соединения.
  • 8. Индексы ● Все тот же принцип — чем меньше, тем лучше – Меньше индекс – Меньше индексов ● Иногда можно и вообще без индексов
  • 9. Индексы btree ● Индекс — это отсортированная последовательность ● (usr_id) ● (usr_id, added) – Если оба реально используются, подумайте, нужны ли оба сразу — оптимизатор выбирает лучший индекс для запроса, а не для всего приложения
  • 10. Порядок строк в индексе ● (usr_id) — usr_id равно/больше/меньше ● (usr_id,added) — usr_id равно/больше/меньше – usr_id равно, added равно/больше/меньше – НЕ РАБОТАЕТ (почти) - added равно/больше/меньше
  • 11. Индексы — LIKE ● Для LIKE индекс используется для поиска по префиксу — LIKE 'str%' ● Не работает для LIKE '%str' ● Внимание — параметры! – Тонкий момент в PostgreSQL
  • 12. Покрытие индексом ● Все колонки есть в индексе ● Меньше обращений к страницам ● Меньше ввод-вывод ● Меньше latches/buffer pin ● Больше индексов/больше индекс
  • 13. Пример create table ios( id int primary key, val text) insert into ios select n, repeat('X', n%100) from generate_series(1,1000000) as gs(n) explain(analyze, verbose,buffers) select count(val) from ios where id between 1 and 100000 explain(analyze, verbose,buffers) select count(id) from ios where id between 1 and 100000
  • 14. План 1 Aggregate (cost=3998.45..3998.46 rows=1 width=8) (actual time=22.241..22.242 rows=1 loops=1) Output: count(val) Buffers: shared hit=816 -> Index Scan using ios_pkey on public.ios … Output: id, val … Buffers: shared hit=816
  • 15. План Бэ Aggregate (cost=3347.30..3347.31 rows=1 width=8) (actual time=16.804..16.804 rows=1 loops=1) Buffers: shared hit=277 -> Index Only Scan using ios_pkey on public.ios … Heap Fetches: 0 Buffers: shared hit=277
  • 16. Сравнение при параллельном выполнении ● 8 клиентов – Обычный доступ — 220.709118 tps – Index-only scan - 336.434901 tps
  • 17. Покрытие индексом ● PostgresPro — INCLUDING ● Покрытие индексом — предпоследний способ повысить производительность ● Почему плохо – На каждый запрос делать индекс — это ж сколько их будет? – Что делать, если запрос поменялся?
  • 18. Методы соединения select * from first, second where first.key=second.key
  • 19. Методы соединения select * from first, second where first.key=second.key select * from first, second where first.key<>second.key
  • 20. Методы соединения select * from first, second where first.key=second.key select * from first, second where first.key<>second.key select * from first, second where exists(select * from third where third.first_key=first.key and third.second_key=second.key)
  • 21. Методы соединения ● Nested loops – for i in first_table ● For j in second_table where second_table.i=i проверяем условия и формируем строку
  • 22. Методы соединения ● Nested loops – for i in first_table ● For j in second_table where second_table.i=i проверяем условия и формируем строку ● Hash join – Строим хэш-таблицу из first_table ● for j in second_table if key_exists(hash(second_table.j)) –проверяем условия и формируем строку – Что делать, если таблица не помещается в память?
  • 23. Методы соединения ● Nested loops – for i in first_table ● For j in second_table where second_table.i=i проверяем условия и формируем строку ● Hash join – Строим хэш-таблицу из first_table ● for j in second_table if key_exists(hash(second_table.j)) –проверяем условия и формируем строку ● Merge join –Сливаем две отсортированных first_table & second_table ● проверяем условия и формируем строку
  • 24. Методы соединения ● Nested loops – За ● Очень дешевый ● Очень быстрый на небольших объемах ● Не требует много памяти ● Идеален для молниеносных запросов ● Единственный умеет соединения не только по равенству – Против ● Плохо работает для больших объемов данных
  • 25. Методы соединения ● Hash join – За ● Не нужен индекс ● Относительно быстрый ● Может быть использован для FULL OUTER JOIN – Против ● Любит память ● Соединение только по равенству ● Не любит много значений в колонках соединения ● Велико время получения первой строки
  • 26. Методы соединения ● Merge join – За ● Быстрый на больших и малых объемах ● Не требует много памяти ● Умеет OUTER JOIN ● Подходит для соединения более чем двух таблиц – Против ● Требует отсортированные потоки данных, что подразумевает или индекс, или сортировку ● Соединение только по равенству
  • 27. Про Postgres ● Не умеет full outer join с соединением не по равенству ● Вот только что-то никто не жаловался :-)
  • 28. Статистика ● В PostgreSQL — pg_statistics или на ее основе представление pg_stats ● Статистика — ключевой фактор для работы оптимизатора ● Проблемы — пары-тройки-четверки колонок ● Oracle — умеет. А вот PostgreSQL — нет :-(
  • 29. Типовые проблемы ● Плохая схема БД – Объемы! ● Лишние данные ● Лишние индексы ● Отсутствие нужных индексов ● Неверные типы – Необходимость писать сложные запросы ● Бездумное использование ОРМ
  • 30. Бездумное использование ОРМ ● Вообще говоря, я его не люблю – Но мало ли что я не люблю. А народу вот нравится ● Типовой запрос: – select distinct <от десятков до сотен колонок> from table1 left outer join table2 on … left outer join table3 on … left outer join table4 on … where table4.col='value' order by table1.id limit 100 offset 20000
  • 31. ОРМ-запрос. Что тут плохо ● DISTINCT – Если вы не можете точно сказать, зачем вы используете DISTINCT, то у вас проблемы
  • 32. ОРМ-запрос. Что тут плохо ● DISTINCT – Если вы не можете точно сказать, зачем вы используете DISTINCT, то у вас проблемы ● LEFT OUTER JOIN – Бьет по рукам оптимизатору, строго задавая порядок соединения – Более того, условия во WHERE делают внешнее соединение ненужным
  • 33. ОРМ-запрос. Что тут плохо ● DISTINCT – Если вы не можете точно сказать, зачем вы используете DISTINCT, то у вас проблемы ● LEFT OUTER JOIN – Бьет по рукам оптимизатору, строго задавая порядок соединения – Более того, условия во WHERE делают внешнее соединение ненужным ● LIMIT/OFFSET почти всегда плохо
  • 34. Что делать? ● Четко определиться, какую бизнес-задачу решает запрос. Возможно, после этого необходимость в нем отпадет ● Разобраться с ОРМ – Выбирать только то, что нужно – Постараться перейти к INNER JOIN – Постараться избавиться от LIMIT/OFFSET
  • 35. Выводы ● Чем меньше, тем лучше ● Знайте ваши данные