Рубріки: Бази даних

Як перестати ненавидіти і полюбити ORM

Володимир Рожков

Серед багатьох досвічених розробників існує думка, що ORM — це щось погане. Його звинувачують в низькому перформенсі, непотрібних абстракціях та вихованню поганого смаку.

Щоразу коли читаю ті історії, то ніяк не можу второпати, що авторам не подобається, бо я з ORM-ами ніяких проблем не маю.

Історія взаємодії з ORM

На першій роботі у бородаті роки в нас був самописний ORM, але він дуже повільно працював (проте мав інші переваги). Ми про цю особливість знали, тому для наших задач написали власний і не знали горя.

Згодом я успішно користувався JPA/Hibernate і мав халепу тільки зі специфічними речами типу bigint, який не хотів мапитися чи то через багу Хібера, чи то через особливості MariaDB.

А після ActiveRecord я не дуже уявляю як можна бути продуктивним без ORM. У всіх своїх проєктах SQL мені доводилося писати тільки для запитів пов’язаних зі статистикою.

Відома моя любов до Rails, але ActiveRecord я люблю найбільше, ось, наприклад запит на витягування чергового щоденного збору для @Donate1024Bot

Post.where(state: "approved")
    .where.not(amount: nil)
    .where.not(goal: nil)
    .where(posted_count: 0)
    .where(scheduled_at: Time.now.utc.to_date)
    .order(:id)
    .first

Ефективна робота з ORM

Не буду по пунктах розбивати класичні аргументи проти, натомість напишу що потрібно вам, щоб бути ефективним.

Головне — добре знати та розуміти SQL. Коли ви вже розумієте як зробити потрібний вам запит то не буде жодних проблем з тим щоб конвертувати його в ефективний ORM-код. Мені здається що часто люди скаржаться на код програмістів які почали користуватися ORM без хороших знань SQL і нарубали дров. Таке звісно нікуди не годиться.

Друге — розібратися, як зробити, щоб ваш ORM-фреймворк друкував у лог всі запити які він генерує та робить. Те що не бачиш, не можеш поміряти та подебажити.

Всі ORM-и вміють це робити, але, з невідомих причин, це не всюди увімкнено за замовчуванням, наприклад, у Spring/JPA це треба конфігурувати окремо. Одна з величезних переваг ActiveRecord — це такий лог. Наприклад, запит зверху покаже нам ось таке:

Post Load (56.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."state" = $1 AND "posts"."amount" IS NOT NULL AND "posts"."goal" IS NOT NULL AND "posts"."posted_count" = $2 AND "posts"."scheduled_at" = $3 ORDER BY "posts"."id" ASC LIMIT $4  [["state", "approved"], ["posted_count", 0], ["scheduled_at", "2023-09-18"], ["LIMIT", 1]]

В консолі воно ще й красиво розфарбовано, тут ми можемо бачити: час виконання запиту, сам запит та «бінди», ті параметри які в нього були передані. Цієї інформації більш ніж достатньо для того, щоб писати ефективні запити.

Третє — розуміти що таке N+1 та як у вашому ORM-фреймворку цього уникнути. Здається що N+1 це найрозповсюдженіша проблема з ORM, на що лаються ті самі досвічені програмісти, хоча вона дуже легко виявляється та виправляється. Просто почитайте як у вас робиться includes або FetchMode.EAGER і більше не матимете з тим клопоту.

Гадаю що 95% всіх проблем з ORM зводиться саме до N+1 та нерозуміння, як з ним впоратися.

Четверте — розуміти ціну створення об’єктів та використовувати методи які дозволяють уникнути цього. Наприклад, якщо нам треба взяти з таблиці тільки одне поле, id, то замість ids = User.all.map(&:id) можна використати ids = User.all.pluck(:id) яке не буде створювати об’єкти User, а дістане лише масив id. Rails люб’язно друкує статистику щодо кількості інстанційованих об’єктів в лог, тому там відразу зрозуміло, де це вже впливає на швидкодію.

Люблю ORM, використовую у всіх проєктах, раджу робити те ж і вам.

Практична порада

Увімкнути логи свого ORM та подивитися на запити які він генерує. Подумати що можна покращити та почитати документацію або Tips&Tricks до свого фреймворку.

Цей текст з особистого блогу, опублікований з дозволу автора.

Якщо ви знайшли помилку, будь ласка, виділіть фрагмент тексту та натисніть Ctrl+Enter.

Останні статті

IT в Україні йде до свого фінального кінця. І потраплятимуть туди виключно за покликом душі

Коротко про українську IT-сферу у 2024 році Це коли на одну вакансію Middle розробника по…

26.03.2024

Блокчейн-розробка сьогодні: зарплати і перспективи на ринку праці

Формування криптовалютної галузі в Україні почалося ще у 2014 – саме тоді з'явилися перші стартапи,…

18.03.2024

Скільки рішень ухвалює розробник? Погляд новачка, який запускає продукт

Автор цього блогу — Python-девелопер Сергій Солдатов, який вирішив створити досить унікальний продукт. І це…

12.03.2024

Чи треба готуватись до співбесіди?

Думки шукачів діляться на: «так, однозначно» і «ні, не вартує, я все і так про…

04.03.2024

Відкладаєте до останнього? Що таке «синдром студента» і як з ним боротися

Синдром студента — це форма прокрастинації, яка полягає в тому, що людина, якій дали завдання,…

23.02.2024

Вчимося працювати з Git: основи конфігурації, гілки, додавання файлів та директорій

Git — це найпопулярніша CVS прямо зараз, яка дозволяє відстежувати історію розробки і спільно працювати.…

20.02.2024