Pull to refresh

Comments 6

У него был уже запрос, который он написал правильно. И он пытался выдрессировать ORM, чтобы тот сгенерировал запрос такого же вида, чтобы он нормально заработал. Бессмысленность этого становится совершенно очевидной.

Очень сильно несогласен с заявлением. Если есть потенциальная возможность затюнить ORM под запрос — то очень часто выгодней все же попытаться такой возможностью воспользоваться. Потому как воспользовавшись Native запросом нередко лишаешься некоторых дополнительных плюшек ORM (готовый маппинг, отслеживание границ транзакций, lazy-поля и т.п).


Естественно, что всё должно быть в пределах разумного: если запрос сильно выбивается из того, что конкретный ORM умеет — то тратить время на "подгонку" скорее всего будет непродуктивно. Но и сразу отказываться от ORM только потому, что у вас есть готовый native запрос — глупо.

Ну здесь очевидно, что запрос, который нужно оптимизировать — не простая выборка по какому-либо условию(для таких запросов ORM плюс-минус без ошибок). Для запросов в которых реально важна производительность — сложные выборки по многим таблицам с большим количеством условий, агрегированные таблицы в JOIN — выдрессировать ORM — задача зачастую просто нереальная. Кроме того не каждый ORM — работает прозрачно для разработчика: когда данные попадают в кэш, когда они оттуда уходят, запрос.
Приведу пример ограничений, который накладывает, допустим Hibernate на базе PostgreSQL:
— нет джойнов по полям таблиц, явно не связанными в мэппинге, допустим для такого запроса:

SELECT a.* FROM a LEFT JOIN b ON a.sum=b.sum WHERE b.type='foo';


— ORM редко когда знает о фичах самой БД. Смэпить тот же JSON/JSONB — достаточно интересная задача с собственным типом данных, а оно зачастую нужно

— никакого CTE — без костылей

— никаких хранимых процедур, нормально вписывающихся в мэппинг сущности

Использовать ORM надо с умом, и там где он применим

Очень хороший доклад. Грамотный базис из очевидных простых вещей (но которые часто многие делают сложно и неправильно) и видно глубокое понимание темы.

Зачем счетчики вырезали? Их надо было просто сделать по нормальному, а не в лоб и былоб всё хорошо.


  1. Счетчики можно кешировать;
  2. Счетчики можно хранить в Redis и пересчитывать по cron;
  3. Счетчики можно хранить в Redis и обновлять по событию из Domain layer.

Последний вариант предпочтительней так как мы всегда имеем актуальные данные в счетчиках и не трогаем БД вообще.


ORM зло? С чего бы? Единственный запрос которые ORM генерит сама, это получение связей, но эти запросы максимально оптимальны. Все остальные запросы составляет сам разработчик используя всякие QueryBuilder-ы которые очень точно транслируют запрос в SQL.
QueryBuilder-ы имеют плюсы по сравнению с plain text запросами, хотя бы потому что их можно использовать в спецификациях и сворачивать большую портянку до одной строчки кода которая очень чётко отражает то что она делвет:


$members = $repository->match(new PublishedMembersWithContest($contest);

Бывают супер сложные запросы с подзапросами, UNION и алгоритмов на основе нумерации строк. Такие запросы можно описать через QueryBuilder с помощью бубна и такой-то матери, но это не нужно. Такие запросы пишутся один раз и используются только в одном месте. Их вполне можно писать и как plain text. Таких запросов один на сто. И все в команде о них знают.


Единственное что делает не оптимально, те ORM с которыми я работал, это выборка в связке ManyToMany одних элементов, по id вторых:


SELECT
    u.*
FROM
    user AS u
INNER JOIN
    users_groups AS ug
    ON
        u.id = ug.user_id
INNER JOIN
    group AS g
    ON
        g.id = ug.group_id
WHERE
    u.enabled = TRUE AND
    g.id = 2;

Второй JOIN делает ORM и он здесь не нужен, но из-за выборки по primary key, мы не имеем проблем с производительелстью.

А зачем руками кешировать счётчики, если примерно то же самое делает СУБД самостоятельно? Достаточно правильно её попросить.

Если я правильно понял, то это вытягивание счетчиков из внутренних таблиц PostgreSQL без обращения к основной таблице.
Ну ок. Это сойдет для простых запросов когда нам нужно просто общее число записей в таблице. Значительно чаще же нам нужны счетчики с выборкой.


  • Сколько активных пользователей?
  • Сколько активных сообществ?
  • Сколько активных пользователей в конкретном сообществе?
  • Сколько фоточек загрузил конкретный пользователь?
  • Сколько комментариев к конкретной статье?
  • Сколько просмотров у конкретной новости?
  • Сколько товаров в конкретной категории?

Как только в запросе появляется WHERE вся эта ваша система разбивается о стену.

Sign up to leave a comment.