Используете ORM или простой SQL?

Для некоторых приложений, которые я разработал (о которых потом забыл), я писал простой SQL, в первую очередь для MySQL. Хотя я использовал ORM в python, как SQLAlchemy, я долго не придерживался их. Обычно это была либо документация, либо сложность (с моей точки зрения), сдерживающая меня.

Я вижу это так: используйте ORM для переносимости, простой SQL, если он просто собирается использовать один тип базы данных. Я действительно ищу совет о том, когда использовать ORM или SQL при разработке приложения, которое нуждается в поддержке базы данных.

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

13 ответов

Решение

У ОРМ есть несколько приятных особенностей. Они могут выполнять большую часть работы по копированию столбцов базы данных в поля объекта. Они обычно обрабатывают преобразование типов даты и времени языка в соответствующий тип базы данных. Как правило, они довольно элегантно обрабатывают отношения "один ко многим", создавая экземпляры вложенных объектов. Я обнаружил, что если вы разрабатываете свою базу данных с учетом сильных и слабых сторон ORM, это экономит много времени при получении данных в базе данных и из нее. (Вы захотите узнать, как он обрабатывает полиморфизм и отношения "многие ко многим", если вам нужно отобразить их. Именно эти две области обеспечивают большую часть "несоответствия импеданса", что делает некоторые из них ORM "вьетнамом компьютерных наук")..)

Для приложений, которые являются транзакционными, то есть вы делаете запрос, получаете некоторые объекты, перебираете их, чтобы получить некоторые данные и отображаете их на веб-странице, налог на производительность невелик, и во многих случаях ORM может быть быстрее, поскольку он будет кэшировать объекты. видел, что в противном случае запросил бы базу данных несколько раз.

Для приложений, которые требуют значительных отчетов или обрабатывают большое количество строк базы данных за запрос, налог на ORM намного тяжелее, и кэширование, которое они выполняют, превращается в большую, бесполезную нагрузку на память. В этом случае простое сопоставление SQL (LinQ или iBatis) или запросы SQL с ручной кодировкой в ​​тонком DAL - это путь.

Я нашел для любого крупномасштабного приложения, которое вы найдете, используя оба подхода. (ORM для простого CRUD и SQL/thin DAL для отчетов).

Говоря как человек, который потратил довольно много времени на работу с JPA (Java Persistence API, в основном стандартизированный ORM API для Java/J2EE/EJB), который включает в себя Hibernate, EclipseLink, Toplink, OpenJPA и другие, я поделюсь некоторыми своими наблюдения.

  1. ОРМ не быстр. Они могут быть адекватными, и в большинстве случаев адекватными - это нормально, но в среде с большими объемами и малой задержкой их нет - нет;
  2. В языках программирования общего назначения, таких как Java и C#, вам нужно очень много магии, чтобы заставить их работать (например, ткачество во время загрузки в Java, инструментарий и т. Д.);
  3. При использовании ORM вместо того, чтобы идти дальше от SQL (что, похоже, и есть намерение), вы будете удивлены, сколько времени вы тратите на настройку XML и / или аннотаций / атрибутов, чтобы ваш ORM генерировал производительный SQL;
  4. Для сложных запросов действительно нет замены. Как и в JPA, есть некоторые запросы, которые просто невозможны, которые находятся в необработанном SQL, и когда вам нужно использовать необработанный SQL в JPA, это не очень красиво (C#/.NET, по крайней мере, имеет динамические типы - var - что много лучше, чем массив объектов);
  5. При использовании ORM очень много "ловушек". Это включает непреднамеренное или непредвиденное поведение, тот факт, что вам необходимо встроить возможность обновления SQL в вашей базе данных (с использованием refresh() в JPA или аналогичными методами, поскольку JPA по умолчанию кэширует все, поэтому он не перехватывает прямую базу данных). обновление - выполнение прямых обновлений SQL является распространенным видом деятельности поддержки производства);
  6. Несоответствие между объектами и отношениями всегда вызывает проблемы. В любой такой проблеме есть компромисс между сложностью и полнотой абстракции. Временами я чувствовал, что JPA зашел слишком далеко и достиг реального закона убывающей доходности, когда сложность не оправдывалась абстракцией.

Есть еще одна проблема, которая требует немного большего объяснения.

Традиционная модель для веб-приложения состоит в том, чтобы иметь уровень персистентности и уровень представления (возможно, между сервисами или другими уровнями между ними, но они являются важными двумя для этого обсуждения). ORM вынуждают строгое представление от вашего уровня персистентности до уровня представления (то есть ваших сущностей).

Одна из критических замечаний относительно более сырых методов SQL заключается в том, что в итоге вы получаете все эти VO (объекты значений) или DTO (объекты передачи данных), которые используются просто одним запросом. Это рекламируется как преимущество ORM, потому что вы избавляетесь от этого.

Дело в том, что эти проблемы не исчезают с ORM, они просто перемещаются на уровень представления. Вместо создания VO /DTO для запросов вы создаете пользовательские объекты презентации, обычно по одному для каждого представления. Как это лучше? ИМХО это не так.

Я написал об этом в ORM или SQL: мы уже там?,

Моя постоянная технология выбора (на Java) в эти дни - ibatis. Это довольно тонкая оболочка для SQL, которая делает на 90% больше того, что может сделать JPA (она может даже выполнять ленивую загрузку отношений, хотя и не очень хорошо документирована), но с гораздо меньшими накладными расходами (с точки зрения сложности и реального кода).

Это появилось в прошлом году в приложении GWT, которое я писал. Много переводов из EclipseLink в объекты презентации в реализации сервиса. Если бы мы использовали ibatis, было бы гораздо проще создать соответствующие объекты с помощью ibatis, а затем передавать их все время вверх и вниз по стеку. Некоторые пуристы могут утверждать, что это Bad™. Может быть, так (в теории), но я скажу вам, что: это привело бы к более простому коду, более простому стеку и большей производительности.

Я говорю простой SQL для чтения, ORM для CUD.

Производительность - это то, что меня всегда беспокоит, особенно в веб-приложениях, а также удобство сопровождения и читаемости кода. Для решения этих проблем я написал SqlBuilder.

ORM - это не просто переносимость (что довольно сложно достичь даже с помощью ORM). То, что он дает, - это, по сути, слой абстракции над постоянным хранилищем, когда инструмент ORM освобождает вас от написания шаблонных SQL-запросов (выбирает по PK или по предикатам, вставляет, обновляет и удаляет) и позволяет сосредоточиться на проблемной области.

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


РЕДАКТИРОВАТЬ в ответ на комментарий с просьбой описать, как я отличаю DAL от ORM:

DAL - это то, что вы пишете сами, возможно, начиная с класса, который просто инкапсулирует таблицу и сопоставляет ее поля со свойствами. ORM - это код, который вы не пишете, или механизмы абстракции, выведенные из других свойств вашей схемы dbms, в основном PK и FK. (Здесь вы узнаете, начинают ли течь автоматические абстракции или нет. Я предпочитаю информировать их намеренно, но это может быть моим личным предпочтением).

Дилемма, использовать ли фреймворк или нет, довольно распространена в современном сценарии разработки программного обеспечения.

Важно понимать, что у каждого фреймворка или подхода есть свои плюсы и минусы - например, из нашего опыта мы обнаружили, что ORM полезен при работе с транзакциями, т.е. операциями вставки / обновления / удаления, - но когда дело доходит до извлечения данных со сложным Результаты становится важным для оценки производительности и эффективности инструмента ORM.

Также важно понимать, что не обязательно выбирать структуру или подход и реализовывать все в этом. Под этим мы имеем в виду, что у нас может быть сочетание ORM и родного языка запросов. Многие платформы ORM предоставляют точки расширения для плагина в нативном SQL. Мы должны стараться не слишком использовать рамки или подходы. Мы можем объединить определенные рамки или подходы и прийти с соответствующим решением.

Вы можете использовать ORM, когда дело доходит до вставки, обновления, удаления, управления версиями с высоким уровнем параллелизма, и вы можете использовать Native SQL для генерации отчетов и длинных списков

Ключ, который сделал мое использование ORM действительно летящим, было генерацией кода. Я согласен, что маршрут ORM не самый быстрый, с точки зрения производительности кода. Но когда у вас средняя и большая команда, БД быстро меняет способность восстанавливать классы и сопоставления из БД, как часть процесса сборки, и это замечательно, особенно когда вы используете CI. Таким образом, ваш код может быть не самым быстрым, но ваш код будет - я знаю, что я бы взял в большинстве проектов.

Моя рекомендация состоит в том, чтобы разрабатывать с использованием ORM, пока Схема все еще изменчива, использовать профилирование для поиска узких мест, а затем настраивать те области, которые в этом нуждаются, используя необработанный SQL.

Другая мысль: кэширование, встроенное в Hibernate, часто может привести к значительным улучшениям производительности при правильном использовании. Больше не нужно возвращаться в БД для чтения справочных данных.

У каждого инструмента есть своя цель и видение. Я создал http://www.jooq.org/ именно для того, чтобы удовлетворить ваши потребности, хотя iBatis, вероятно, также является хорошим решением для вас.

В jOOQ есть основные функции ORM, но в основном он сосредоточен на вещах, которые, как мне кажется, большинству разработчиков нужны больше всего, когда они пытаются найти лучший ORM для своих нужд:

  • генерация кода
  • привязка к переменной (это боль в JDBC)
  • Синтаксическая абстракция SQL (для предотвращения синтаксических ошибок)

Но часто они заходят слишком далеко и предоставляют так много абстракций, что вы не думаете, что они работают против СУБД. С другой стороны, вы выбрали СУБД именно потому, что

  • это надежный источник данных
  • SQL может делать много хороших, производительных вещей (вложенные выборки, объединения, сложные объединения и т. Д.). Часто ORM не может делать такие вещи.
  • вы можете обрабатывать транзакции и сессии самостоятельно
  • у вас есть UDT и хранимые процедуры

JOOQ обращается именно к этим пунктам. Он будет работать так же хорошо, как JDBC, но без боли.

Не существует единого решения для всех инструментов, и это также верно для вопроса "использовать или / или нет? ".

Я бы сказал: если вам нужно написать приложение / инструмент, ориентированный на "данные", без особой логики, то я бы использовал простой SQL, поскольку SQL является предметно-ориентированным языком для такого рода приложений.

С другой стороны, если бы я должен был написать приложение для бизнеса / предприятия, которое содержит много логики "предметной области", то я написал бы богатую модель классов, которая могла бы выразить этот домен в коде. В таком случае, маппер OR/M может быть очень полезен для успешного выполнения, так как он забирает много сантехнического кода из ваших рук.

Я знаю, что этот вопрос очень старый, но я подумал, что опубликую ответ, если кто-нибудь сталкивается с ним, как я. ОРМ прошли долгий путь. Некоторые из них на самом деле дают вам лучшее из обоих миров: повышение эффективности разработки и поддержание производительности.

Посмотрите на данные SQL ( http://sqldata.codeplex.com/). Это очень легкий ORM для C#, который охватывает все базы.

К вашему сведению, я автор данных SQL.

Одним из приложений, которые я разработал, был бот IRC, написанный на python. Модули, которые он использует, работают в отдельных потоках, но я не нашел способа справиться с многопоточностью при использовании sqlite. Хотя это может быть лучше для отдельного вопроса.

Я действительно должен был перефразировать и название, и сам вопрос. Я никогда не использовал DAL раньше, на любом языке.

Используйте ORM, который работает как SQL, но обеспечивает проверки во время компиляции и безопасность типов. Как и мой любимый: объекты знаний данных (раскрытие: я написал это)

Например:

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

Полностью потоковое Простота установки (нет сопоставлений для определения - читает ваши существующие схемы). Поддерживает объединения, транзакции, внутренние запросы, агрегирование и т. Д. Практически все, что вы можете делать в SQL. И было доказано от гигантских наборов данных (финансовых временных рядов) вплоть до тривиального (Android).

Я хотел бы добавить свой голос в хор ответов, которые говорят: "Там есть середина!".

Для программиста приложений SQL - это смесь вещей, которыми вы, возможно, захотите управлять, и вещей, которыми вы почти наверняка не захотите управлять.

То, что я всегда хотел, это слой (назовите его DAL, ORM или микро-ORM, я не против чего), который будет отвечать за полностью предсказуемые решения (как правильно писать ключевые слова SQL, куда идут круглые скобки, когда придумывать псевдонимы столбцов, какие столбцы создавать для класса, который содержит два числа с плавающей запятой и int ...), оставляя меня ответственным за аспекты более высокого уровня SQL, то есть как организовать JOIN, вычисления на стороне сервера, DISTINCT, GROUP BY, скалярные подзапросы и т. Д.

Поэтому я написал кое-что, что делает это: http://quince-lib.com/

Это для C++: я не знаю, какой язык вы используете, но все же было бы интересно посмотреть, как это "среднее положение" может выглядеть.

Другие вопросы по тегам