Якщо вам потрібно відмовитися від системи ORM, коли вам потрібно здійснити об'ємну операцію?


15

Ось загальна ситуація:

  • Вам потрібно реалізувати операцію масового використання в додатку, що використовує рамку ORM.
  • Після першого пропуску ви помітили значні проблеми з продуктивністю.

Ось моє запитання:

  • У цій ситуації ви повинні надавати перевагу рішенню, яке включає необроблений SQL?
  • Або є відомі моделі дизайну, які можуть допомогти вам пом’якшити проблеми, які зазвичай пов’язані з масовими операціями з рамками ORM?

Редагувати:

  • Я не запитую, чи слід вилучати рамку ORM з усієї програми.
  • Я запитую: чи варто вам відмовитися від системи ORM для цього невеликого фрагмента програми?

Я не знаю , якщо ви повинні зробити що - небудь, але ви пробували дозування масової операції?
ChrisAnnODell

Відповіді:


13

ORM не мають на меті повністю перейняти доступ до вашої бази даних. Використовуйте їх для тих 80% коду, який є CRUD, те, що надто виснажливо писати самостійно. Використовуйте збережені процедури, динамічний SQL або все, що вам потрібно, для решти 20%, які потрібно ретельно оптимізувати.


4
Це спрацювало б, якщо абстракція бази даних не була однією з головних причин, чому ви вирішили використовувати ORM.

@ Pierre303, мені важко зрозуміти ваш коментар. Що ви маєте на увазі?
Марк Канлас

@MarkCanlas: Я думаю, що він означає "абстрагування бази даних", в тому сенсі, що ви можете змінити базу даних (наприклад, перейти з SQL Server на MySQL), якщо хочете це зробити. На практиці такого випадку використання майже не зустрічається.
Роберт Харві

1
Ви все одно можете створювати абстракції. Більшість ORM, які фактично підтримують декілька постачальників / діалектів, мають підтримку коду, що відповідає постачальнику / діалекту. Ви можете реалізовувати операції як об'ємна вставка / прив'язка масиву / TVP / будь-яка для конкретних баз даних, і дозволити їй повертатися до повільного для непідтримуваних постачальників, таких як SQLite. У гіршому випадку ви можете розбити потужну функціональність в окремий інтерфейс / клас та підрозділ в іншій реалізації на основі параметрів збірки або конфігурації.
Aaronaught

Так, індивідуальні діалекти можуть допомогти, а також конкретний код для конкретних проблем. Однак, щоб це було життєздатним з фінансової точки зору, це повинно бути обмежено суворим мінімумом. Наші налаштування за допомогою спеціальних функцій (діалектів) становлять менше 0,1% від загальної бази доступу до даних. Я був би дуже стурбований, якби це було більше.

7

Я використовую ORM (nHibernate) у додатку, який вимагає високої продуктивності та обробляє мільярди записів. З часом ми помітили, що найбільш значні проблеми з продуктивністю були пов’язані з нашим власним способом використання ОРМ, а не через ОРМ.

ORM не повинен замінювати ваші обов'язкові знання бази даних. Це інструмент, який ви використовуєте для отримання більшої продуктивності та гнучкості в коді, але вам потрібно знати основні процеси, щоб оптимізувати свою ефективність.

Ви не вказали конкретний ORM, тому ось що ми зробили для підвищення продуктивності:

  • Ми використовували ORM-профілер. (ми використовували nhprof)
  • Ми використовували профайлер бази даних. (ми використовували Profiler SQL Server)
  • Ми читаємо якомога більше статей на цю тему. (Багато було доступно для nHibernate на додаток до всього розділу з цього питання в документації)
  • Ми купували конкретні книги про продуктивність та масштабованість.
  • Ми створили систему бенчмаркінгу для перевірки власних оптимізацій.
  • і що ще важливіше, ми змогли протестувати наш код із реальними клієнтами з величезними даними. Останнє лише допомогло нам помітити більшість проблем у нашому додатку.

1

Нам вдалося це зробити за допомогою Entity Framework, але наша програма зробила багато операцій у стилі пакетної роботи (ми б писали велику кількість записів до окремих таблиць), тому це було добре. Я б точно визначив, чи вдасться зберегти рамку ORM, якщо можливо, просто зменшити кількість коду спеціального призначення у вашому додатку. Чи можна буферувати записи, а потім виконувати їх як групу? Ви втрачаєте семантику транзакцій, але якщо ви працюєте з масовими операціями, я припускаю, що ви вже з цим погодилися.


1

ORM не роблять нічого магічного. Вони переводять методи доступу до об'єктів у SQL. Виконання SQL-операторів, які вони виконують, не обов'язково повільніше, ніж SQL, який ви писали б вручну. Сказавши це, ви можете натрапити на кілька питань:

  1. Операції: одна велика об'ємна операція майже завжди швидша, ніж багато дрібних транзакцій, які разом здійснюють одне і те ж. Отже, якщо ваші виклики методу ORM використовують дрібнозернисті транзакції (наприклад, активні методи запису в об'єктах Spring Roo позначаються як @Transactional за замовчуванням), групові операції будуть повільними. Якщо це так у вашій заявці, слід переглянути свою логіку транзакцій.
  2. Кешування: у режимі сплячого режиму кеш першого рівня дозволяє вашому керівнику сутності уникати незвичних об’їзних переходів до бази даних. Хороша річ загалом, але погана для об'ємних вставок, де це призводить до непотрібних забивань кешу, що призводить до погіршення продуктивності програми. Якщо це ваша проблема, ви повинні подивитися на схему Batching, запропоновану вище ChrisAnnODell. Ми використовуємо його у своїх імпортерів, і це значно прискорює об'ємні вставки.

Немає нічого поганого в тому, щоб використовувати рідний SQL для підвищення продуктивності. Але спочатку переконайтеся, що ви зрозуміли, що сповільнює вас.


Щоб уникнути кешу, використовуйте сеанс без громадянства. Крім того, уникайте ідентифікаторів автоматичного збільшення. Натомість слід використовувати HiLo або Guid.

1

Обхід ORM. Мало того, але й обхід "регулярного" sql. Використовуйте об'ємну утиліту вашої бази даних, щоб вставити надзвичайно великі набори даних у таблицю постановки. Потім використовуйте sql для виконання інсценізації.

Ваш ORM "аромат блогу" може працювати не в усіх ситуаціях.


Правильно, подібні інструменти "бек-енд" - це клопот навчитися, але приблизно через 3 або 4 рази ви станете експертом і зможете робити речі швидше, а іноді й речі, які неможливо зробити іншими способами. Це як різниця між лопатою та бульдозером. Я написав інструменти, керовані сценаріями для різних платформ для читання файлів введення тексту та оновлення даних при операціях низького рівня. Написання такого інструменту також може полегшити ваше життя (або принаймні цікавіше). Такі речі можна використовувати для налаштування даних про налаштування клієнтських установок під час оновлення програмного забезпечення.

0

Був у такій ситуації. Іноді доводиться.

Деякі ORM дозволяють розробнику пропускати об'єктну модель і переходити прямо до рівня бази даних.

Є також ORM, які використовують об'ємні операції, капсульовані, як об'єктно-орієнтовані.


0

Як згадував umlcat , є деякі ORM, які дозволять вам використовувати масові операції.

Ще краще, що багато ORM є розширюваними, тому ви можете просто написати свій власний метод для масових операцій, якщо вони вже не підтримуються. Якщо об'ємна операція у вашому додатку - це те, що ви можете визначити, я б додав її як шар на ORM (для цього вам, ймовірно, потрібно буде написати необроблений SQL), але тоді в додатку використовуйте ORM метод, який ви реалізували.

Це також полегшує тестування та налагодження пристрою. Щойно ви отримаєте хороший тестовий покрив для своїх методів ORM, ви можете використовувати його у своїх програмах. В іншому випадку, налагодження сирої SQL (особливо великих з трансакціями та багатьма JOIN) може бути болем.

Одного разу мені знадобилося майже день, щоб помітити помилку в сирому виклику SQL, який був майже 100 LOC, і помилка була лише одним символом! З тих пір я намагаюся уникати необмеженого SQL у додатку та проходити тестування всіх процедур SQL окремо.


0

Добре, що я не знаю жодних дизайнерських малюнків. Я здогадуюсь, що ви прийняли рішення для ORM з причини, тому відмова від ORM, швидше за все, не те, що ви хочете. Однак у цих випадках я думаю, що є можливість змішати обидва рішення. У цьому немає нічого поганого, якщо ви це робите чітко і документуєте, чому ви відхиляєтесь від використання ORM за замовчуванням у вашому програмному забезпеченні. Поруч з цим деякі структури ORM мають деякі можливості для масових операцій. Я знаю, що nHibernate (ORM для .NET Framework) має так звані StatelessSessions, які мають набагато менші накладні витрати, але це все одно може не надати вам підвищення продуктивності. У цьому випадку просто використовуйте необроблений SQL.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.