Używasz ORM lub zwykłego SQL? [Zamknięte]

245

W przypadku niektórych aplikacji, które opracowałem (potem zapomniałem), piszę zwykły SQL, głównie dla MySQL. Chociaż używałem ORM w pythonie, takich jak SQLAlchemy , nie trzymałem się ich długo. Zwykle powstrzymywała mnie dokumentacja lub złożoność (z mojego punktu widzenia).

Widzę to tak: użyj ORM dla przenośności, zwykłego SQL, jeśli tylko będzie korzystał z jednego rodzaju bazy danych. Naprawdę szukam porady, kiedy używać ORM lub SQL podczas tworzenia aplikacji, która wymaga obsługi bazy danych.

Myśląc o tym, zdecydowanie lepiej byłoby użyć lekkiego opakowania do obsługi niespójności bazy danych niż przy użyciu ORM.

hydrapetetz
źródło
Standaryzacja, bezpieczeństwo, łatwość konserwacji, abstrakcja języka, DRY itp.
Ben
Wydajność z ORM może być zbliżona do SQL, zależy od tego, czy używasz go poprawnie i przy prawidłowych ustawieniach ... Zobacz ho, aby EF6.x 5x szybszy: linkedin.com/pulse/…
baHI
Aby zapoznać się z architekturą ORM i instrukcją (czego należy unikać), oto mój kolejny link: linkedin.com/pulse/...
baHI
Mapowanie obiektowo-relacyjne (ORM) jest już bardzo popularne w wielu językach programowania i jest jedną z najlepszych alternatyw dla SQL. Zainspirowałem się stylem tworzenia łańcuchów metod do tworzenia CQL dla mojego projektu TRIADB. healis.eu/triadb/#latest-release
Athanassios
2
To głupie, że to pytanie zostało zamknięte.
Mitch Wheat

Odpowiedzi:

169

ORM mają kilka fajnych funkcji. Potrafią poradzić sobie z wieloma problemami związanymi z kopiowaniem kolumn bazy danych do pól obiektowych. Zwykle obsługują konwersję typów daty i godziny języka na odpowiedni typ bazy danych. Zazwyczaj bardzo elegancko obsługują relacje jeden do wielu, tworząc instancję obiektów zagnieżdżonych. Przekonałem się, że jeśli projektujesz swoją bazę danych z uwzględnieniem mocnych i słabych stron ORM, oszczędza to dużo pracy przy pobieraniu i wyprowadzaniu danych z bazy. (Jeśli chcesz je zmapować, będziesz chciał wiedzieć, jak radzi sobie z polimorfizmem i relacjami wiele do wielu. To te dwie domeny zapewniają większość „niedopasowania impedancji”, przez co niektórzy nazywają ORM „wietnamem informatyki” .)

W przypadku aplikacji transakcyjnych, tj. Składających żądanie, pobierających niektóre obiekty, przechodzących je w celu uzyskania niektórych danych i renderowania ich na stronie internetowej, podatek od wydajności jest niewielki, aw wielu przypadkach ORM może być szybszy, ponieważ buforuje obiekty, jak widzieliśmy wcześniej, w przeciwnym razie wielokrotnie sprawdzałby bazę danych.

W przypadku aplikacji, które są obciążone raportowaniem lub zajmują się dużą liczbą wierszy bazy danych na żądanie, podatek od ORM jest znacznie wyższy, a buforowanie, które wykonują, staje się dużym, bezużytecznym obciążeniem pamięci. W takim przypadku wystarczy proste mapowanie SQL (LinQ lub iBatis) lub ręcznie kodowane zapytania SQL w cienkim DAL.

Znalazłem dla każdej aplikacji na dużą skalę, którą znajdziesz przy użyciu obu metod. (ORM dla prostych CRUD i SQL / cienkich DAL do raportowania).

Cameron Pope
źródło
Czy możesz zdefiniować „dużą liczbę wierszy bazy danych na żądanie”? Proszę :)
Mosselman
Czy mogę na przykład zintegrować JPA z IBatis? I sprawić, by działały w tej samej transakcji?
Jaime Hablutzel,
2
Innym zagadnieniem, o którym nikt nie dyskutuje, jest podstawowe zarządzanie państwem. Cały stos struktur (JSF, JPA itp.) Oparty jest na metodach get / set dla komponentów bean Java. To TONA płyty kotłowej dla każdego stołu, dla każdej kolumny i ... oto prawdziwy anty-wzór: po prostu odsłonić każde pole, jakby było publiczne. W efekcie posiadanie metody get / set na polach w obiekcie / tabeli / rzędzie jest bardzo bliskie naruszeniu każdego lokatora ukrywania i enkapsulacji informacji. Wreszcie, wracając do zarządzania państwem ... gdzie jest opcja niezmienności? Czy można, czy należy dopuścić obiekty w połowie ustalone? Brak opcji dla większości.
Darrell Teague,
2
Chciałbym dopracować, a szczególnie zgodzić się na kluczowe oświadczenie w tej odpowiedzi. „W przypadku aplikacji, które zajmują się dużą liczbą wierszy bazy danych na żądanie, podatek od ORM jest znacznie wyższy”. ORM jest dobry tylko dla programistów i konserwacji, ponieważ większość programistów nie jest zbyt dobra w SQL, ale jeśli faktycznie mówisz o wydajności, SQL całkowicie ją przebija.
Manachi
„większość programistów nie jest zbyt dobra w SQL” ??? Powiedziałbym, że większość programistów nie wie, jak właściwie używać LINQ, mocy drzew wyrażeń i ogólnie ORM, generowania kodu i wielu innych rzeczy. Ale nie, nie mam podstaw do złożenia tak mocnego oświadczenia.
Adanay Martín
253

Mówiąc jako ktoś, kto spędził sporo czasu pracując z JPA (Java Persistence API, w zasadzie znormalizowany ORM API dla Java / J2EE / EJB), który obejmuje Hibernate, EclipseLink, Toplink, OpenJPA i inne, podzielę się niektórymi moimi obserwacje.

  1. ORM nie są szybkie. Mogą być odpowiednie i przez większość czasu wystarczające jest OK, ale w środowisku o dużych opóźnieniach i małych opóźnieniach są nie-nie;
  2. W językach programowania ogólnego przeznaczenia, takich jak Java i C #, potrzeba ogromnej ilości magii, aby mogły działać (np. Tkanie w czasie ładowania w Javie, oprzyrządowanie itp.);
  3. Korzystając z ORM, zamiast wchodzić dalej w SQL (co wydaje się być intencją), będziesz zaskoczony, ile czasu spędzasz na ulepszaniu XML i / lub adnotacji / atrybutów, aby ORM wygenerował wydajny SQL;
  4. W przypadku złożonych zapytań tak naprawdę nie ma substytutu. Podobnie jak w JPA, istnieje kilka zapytań, które po prostu nie są możliwe, które są w surowym SQL, a kiedy trzeba użyć surowego SQL w JPA, to nie jest ładne (C # /. Net przynajmniej ma typy dynamiczne - var - co jest dużo ładniejszy niż tablica obiektów);
  5. Podczas korzystania z ORM jest bardzo dużo „gotchas”. Obejmuje to niezamierzone lub nieoczekiwane zachowanie, fakt, że musisz wbudować możliwość wykonywania aktualizacji SQL bazy danych (za pomocą funkcji refresh () w JPA lub podobnych metodach, ponieważ JPA domyślnie buforuje wszystko, aby nie przechwycić bezpośredniej bazy danych aktualizacja - uruchamianie bezpośrednich aktualizacji SQL jest częstym działaniem wspierającym produkcję);
  6. Niedopasowanie obiektowo-relacyjne zawsze będzie powodować problemy. Przy każdym takim problemie występuje kompromis między złożonością a kompletnością abstrakcji. Czasami czułem, że JPA posunął się za daleko i osiągnął prawdziwe prawo malejących zwrotów, w których złożoność nie była uzasadniona abstrakcją.

Jest jeszcze jeden problem, który wymaga nieco więcej wyjaśnień.

Tradycyjny model aplikacji internetowej ma warstwę utrwalającą i warstwę prezentacji (być może z usługami lub innymi warstwami pomiędzy nimi, ale są to dwie ważne w tej dyskusji). ORM wymuszają sztywny widok od twojej warstwy trwałości do warstwy prezentacji (tj. Twoich jednostek).

Jedną z krytyk bardziej surowych metod SQL jest to, że otrzymujesz wszystkie VO (obiekty wartości) lub DTO (obiekty przesyłania danych), które są używane przez jedno zapytanie. Jest to reklamowane jako zaleta ORM, ponieważ się tego pozbywasz.

Chodzi o to, że problemy te nie znikają z ORM, po prostu przechodzą do warstwy prezentacji. Zamiast tworzyć VO / DTO dla zapytań, tworzysz niestandardowe obiekty prezentacji, zwykle po jednym dla każdego widoku. Jak to jest lepsze? IMHO nie jest.

Pisałem o tym w ORM lub SQL: Czy już tam jesteśmy? .

Moją wybraną obecnie technologią trwałości (w Javie) jest ibatis. Jest to dość cienkie opakowanie wokół SQL, które robi ponad 90% tego, co potrafi JPA (może nawet leniwie ładować relacje, chociaż nie jest to dobrze udokumentowane), ale ma znacznie mniejszy narzut (pod względem złożoności i faktycznego kodu).

Tak było w zeszłym roku w aplikacji GWT, którą pisałem. Wiele tłumaczeń z EclipseLink na obiekty prezentacji w implementacji usługi. Gdybyśmy korzystali z ibatis, znacznie łatwiej byłoby stworzyć odpowiednie obiekty za pomocą ibatis, a następnie przekazać je w górę iw dół stosu. Niektórzy puryści mogą argumentować, że to Bad ™. Być może tak (teoretycznie), ale powiem ci: co prowadziłoby do prostszego kodu, prostszego stosu i większej wydajności.

Cletus
źródło
2
Zainspirowałem się do opublikowania kolejnego (choć społecznościowego wiki) pytania, aby zebrać zasoby na takie tematy. W odniesieniu do ostatniego akapitu: lubię prostotę. Prawdopodobnie za dużo.
hydrapheetz
3
iBATIS jest świetny, ale może zechcesz wypróbować jOOQ: jooq.sourceforge.net . Jego głównym celem jest właśnie pozostanie blisko SQL z 6 powodów, o których wspomniałeś.
Lukas Eder,
5
+1 za punkt 3. Wielu uważa, że ​​korzystanie z ORM uwalnia cię od dokładnego zrozumienia języka SQL. Chodzi o to, że kiedy będziesz w stanie / uczyć się gimnastyki z SQL, prawdopodobnie szybko odejdziesz od ORM ...
Ryan Fernandes
4
A więc teraz jest koniec 2013 r. I jak wszyscy wiemy, nic nie może być bardziej mylące niż „stare fakty” - więc mogę zapytać, czy twoje punkty są nadal takie same? Jeśli nie, dobrze byłoby napisać wpis na blogu / odpowiednio zaktualizować swoją odpowiedź.
Dominik
3
var nie tworzy typu dynamicznego w .NET, zmienne z dynamicznym słowem kluczowym są typami dynamicznymi w .NET. var nadal jest statycznym typowaniem. Zobacz stackoverflow.com/questions/961581/...
Fazi
45

Mówię zwykły SQL dla R eadów, ORM dla CUD .

Wydajność jest czymś, co zawsze mnie martwi, szczególnie w aplikacjach internetowych, ale także łatwość utrzymania kodu i czytelność. Aby rozwiązać te problemy, napisałem SqlBuilder .

Max Toro
źródło
1
Co to jest CUD? Nie mogę znaleźć definicji.
Kimchi Man,
27
@KimchiMan CRUD bez R.
Max Toro
3
CUD - Twórz, aktualizuj, usuwaj.
Połącz
14

ORM to nie tylko przenośność (co jest dość trudne do osiągnięcia nawet w przypadku ORM). To, co daje, to w zasadzie warstwa abstrakcji nad trwałym sklepem, gdy narzędzie ORM uwalnia cię od pisania zapytań SQL typu „podstawowa” (wybieranych przez PK lub według predykatów, wstawiania, aktualizacji i usuwania) i pozwala ci skoncentrować się na domenie problemowej.

Anton Gogolev
źródło
3
Myślałem o czymś bliższym możliwości przenoszenia w różnych wersjach bazy danych. Nie powinnam publikować pytań późno w nocy.
hydrapheetz
1
Właśnie to mówiłem: nawet najbardziej podstawowe scenariusze mogą potencjalnie podlegać błędom w różnych DBMS - na przykład różna obsługa wartości NULL.
Anton Gogolev
ORM daje warstwę abstrakcji nad relacjami między obiektami, ale nie ma żadnej wielkiej przewagi w odniesieniu do wspomnianych zapytań na temat kotłów. W aplikacji JDBC możesz pisać zapytania tego typu z niewielką ilością kodu w abstrakcyjnej nadklasie lub klasie narzędziowej. Nie ma potrzeby powtarzania płyty kotła dla każdego nowego stołu.
Kevin Stembridge
11

Każdy poważny projekt będzie wymagał pewnej abstrakcji dla bazy danych, aby poradzić sobie z niedopasowaniem impedancji. Ale najprostszym pierwszym krokiem (i odpowiednim dla większości przypadków), jakiego oczekiwałbym, byłby DAL, a nie ciężki ORM. Twoje jedyne opcje nie są na końcu spektrum.


EDYCJA w odpowiedzi na komentarz z prośbą o opisanie, w jaki sposób odróżniam DAL od ORM:

DAL jest tym, co sam piszesz, być może zaczynając od klasy, która po prostu kapsułkuje tabelę i mapuje jej pola na właściwości. ORM to kod, którego nie piszesz, ani mechanizmy abstrakcyjne wywodzące się z innych właściwości schematu dbms, głównie PK i FK. (W tym miejscu dowiadujesz się, czy automatyczne abstrakcje zaczynają być nieszczelne. Wolę informować je celowo, ale to może być moja osobista preferencja).

dkretz
źródło
2
Gdzie wyznaczasz granicę między tym, co jest DAL, a co ORM?
chaos
4
Więc jeśli jesteś autorem ORM, ORM automatycznie zmienia się w DAL? :)
Bombe,
DAL = warstwa trwałości i ORM to narzędzie używane w DAL do wykonywania operacji CRUD w magazynie danych.
Vahid Ghadiri
7

Każde narzędzie ma swój cel i wizję. Stworzyłem http://www.jooq.org/ dokładnie dla twoich potrzeb, choć iBatis jest prawdopodobnie również dobrym rozwiązaniem dla ciebie.

jOOQ ma podstawowe funkcje ORM, ale koncentruje się głównie na rzeczach, które, jak sądzę, najbardziej potrzebują programiści, gdy starają się znaleźć najlepszą ORM dla swoich potrzeb:

  • generowanie kodu
  • zmienne wiązanie (to jest problem w JDBC)
  • Abstrakcja składni SQL (aby zapobiec błędom składni)

Ale często posuwają się za daleko i zapewniają tak dużo abstrakcji, że nie sądzisz, że działają przeciwko RDBMS. Z drugiej strony wybrałeś RDBMS właśnie dlatego

  • to solidne źródło danych
  • SQL potrafi wiele dobrych, wydajnych rzeczy (zagnieżdżone selekcje, związki, złożone sprzężenia itp.). Często ORM nie może robić tych rzeczy.
  • możesz samodzielnie obsługiwać transakcje i sesje
  • masz UDT i procedury składowane

jOOQ zajmuje się dokładnie tymi punktami. Będzie działał równie dobrze jak JDBC, ale bez bólu.

Lukas Eder
źródło
6

Dylemat, czy używać frameworka, czy nie, jest dość powszechny we współczesnym scenariuszu tworzenia oprogramowania.

Ważne jest, aby zrozumieć, że każda struktura lub podejście ma swoje zalety i wady - na przykład z naszego doświadczenia wynika, że ​​ORM jest przydatny w transakcjach, tj. Operacjach wstawiania / aktualizacji / usuwania - ale w przypadku pobierania złożonych danych wyniki staje się ważne, aby ocenić wydajność i skuteczność narzędzia ORM.

Ważne jest również, aby zrozumieć, że nie jest obowiązkowe wybranie ram lub podejścia i wdrożenie w tym wszystkiego. Rozumiemy przez to, że możemy mieć połączenie ORM i natywnego języka zapytań. Wiele frameworków ORM daje punkty rozszerzeń wtyczki w natywnym SQL. Powinniśmy starać się nie używać nadmiernie ram ani podejścia. Możemy łączyć określone ramy lub podejścia i dostarczać odpowiednie rozwiązanie.

Możesz użyć ORM, jeśli chodzi o wstawianie, aktualizację, usuwanie, wersjonowanie z wysokim poziomem współbieżności, a także możesz używać Native SQL do generowania raportów i długich list

Rutesh Makhijani
źródło
3
Dlaczego ORM jest lepszy dla wysokiej współbieżności?
user359996 27.01.11
6

Kluczem, który sprawił, że mój ORM naprawdę zaczął latać, było generowanie kodu. Zgadzam się, że trasa ORM nie jest najszybsza pod względem wydajności kodu. Ale kiedy masz średni lub duży zespół, DB szybko zmienia zdolność do regeneracji klas i mapowań z DB jako część procesu kompilacji, jest to coś wspaniałego do zobaczenia, szczególnie gdy używasz CI. Twój kod może nie być najszybszy, ale kodowanie będzie - wiem, co bym wziął za większość projektów.

Moje zalecenie to opracowanie przy użyciu ORM, gdy schemat jest jeszcze płynny, skorzystaj z profilowania, aby znaleźć wąskie gardła, a następnie dostrój te obszary, które tego potrzebują, używając surowego Sql.

Inna myśl, buforowanie wbudowane w Hibernację może często znacznie poprawić wydajność, jeśli jest używane we właściwy sposób. Nie trzeba już wracać do bazy danych, aby odczytać dane referencyjne.

MrTelly
źródło
2
Absolutnie kwestia osobistego gustu. Generowanie kodu jest dla mnie wadą.
dkretz
5
Przeczytaj drugi akapit ... może kompletność też jest przydatna
MrTelly
Generowanie kodu jest jedynym sposobem na szybsze wykonanie niektórych zadań. Jak wszystkie narzędzia, może być potężny lub prowadzić do katastrofy. Technicznie wszystkie języki produkują inne typy kodu.
Banjocat
4

Nie ma rozwiązania „jedno narzędzie dla wszystkich”, a dotyczy to również pytania „czy powinienem używać or / m, czy nie? „.

Powiedziałbym: jeśli musisz napisać aplikację / narzędzie, które jest bardzo „skoncentrowane na danych”, bez większej logiki, użyłbym zwykłego SQL, ponieważ SQL jest językiem specyficznym dla domeny dla tego rodzaju aplikacji.

Z drugiej strony, gdybym miał napisać aplikację biznesową / korporacyjną, która zawiera dużo logiki „domeny”, napisałbym bogaty model klasy, który mógłby wyrażać tę domenę w kodzie. W takim przypadku maper OR / M może być bardzo pomocny, aby to zrobić skutecznie, ponieważ wymaga dużo kodu instalacyjnego z twoich rąk.

Frederik Gheysels
źródło
„Nie ma rozwiązania„ jedno narzędzie dla wszystkich ”… cóż, powinno być.
Rushino
1

Jedną z opracowanych przeze mnie aplikacji był bot IRC napisany w języku python. Moduły, których używa, działają w osobnych wątkach, ale nie znalazłem sposobu na obsługę wątków podczas korzystania z sqlite. Chociaż może to być lepsze w przypadku osobnego pytania.

Naprawdę powinienem był przeredagować zarówno tytuł, jak i pytanie. Nigdy wcześniej nie korzystałem z DAL w żadnym języku.

hydrapetetz
źródło
4
Uważam, że powinieneś. Surowy SQL wszędzie jest dość obrzydliwy.
chaos
No tak. Od czasu do czasu hackuję oprogramowanie forum, które ma mnóstwo mysql_query () i mysql_result () w każdym miejscu. To orzechy.
hydrapheetz
O czym jest ta „aplikacja”, o której mówisz?
Zoran Pavlovic,
To zabawne, że to pytanie zostało zadane przez aplikację irc bot i stało się tym, czym było (bardzo przydatny przewodnik)! Aplikacja irc bot znajduje się na jednym końcu skali, a aplikacja, która ma 50-100+ tabel ze złożonymi złączeniami i milionami wierszy danych z ponad 20 programistami pracującymi nad nią, znajduje się na skrajnym drugim końcu skali. Śmiem twierdzić, że jeśli chodzi o koniec „irc bot app” na skali, to nie ma znaczenia.
Manachi
1

Użyj ORM, który działa jak SQL, ale zapewnia sprawdzanie czasu kompilacji i bezpieczeństwo typu. Podobnie jak moje ulubione: Data Knowledge Objects (ujawnienie: napisałem to)

Na przykład:

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

Pełna transmisja strumieniowa. Łatwy w konfiguracji (brak mapowań do zdefiniowania - odczytuje istniejące schematy). Obsługuje sprzężenia, transakcje, zapytania wewnętrzne, agregację itp. Niemal wszystko, co możesz zrobić w SQL. Udowodniono to od gigantycznych zestawów danych (finansowe szeregi czasowe) aż po trywialne (Android).

Keredson
źródło
Twoje IDE może również zapewniać takie kontrole statyczne bezpośrednio (IDEA zna strukturę DB, więc powiedz jej, gdzie jest DB / gdzie znajdują się pliki DDL, więc może wykonywać sprawdzanie typów / sprawdzanie relacji / itp. W twoich zapytaniach / procedurach SQL / cokolwiek innego )
Xenos
to jest przydatne. czy można to zrobić w ramach kroku kompilacji / CI? jak klasyfikuje sql w porównaniu do innych ciągów? czy poradzi sobie z manipulacją ciągami, czy tylko stałymi ciągami?
keredson
Zostanie zablokowany przez abBlock, ale IntelliJ analizuje SQL jak każdy inny język jetbrains.com/datagrip/features, aby można było zintegrować go z CI / CD / build (może prosząc zespół IJ o wyodrębnienie kodu parsującego SQL? Może już Sonar ma taki parser). Parsowanie przynosi typ danych, dzięki czemu można dodawać do nich kontrole (zrobiłem to z niestandardową wtyczką) lub kontrole typu „czy kolumny JOIN mają indeks FK?” itd. Byłyby to fajne ulepszenia inspekcji SQL natywnych IJ
Xenos
1

Wiem, że to pytanie jest bardzo stare, ale pomyślałem, że opublikuję odpowiedź na wypadek, gdyby ktoś trafił na nią tak jak ja. ORM przeszły długą drogę. Niektóre z nich zapewniają najlepsze z obu światów: zwiększanie produktywności i utrzymanie wydajności.

Spójrz na dane SQL ( http://sqldata.codeplex.com ). Jest to bardzo lekki ORM dla c #, który obejmuje wszystkie podstawy.

Do Twojej wiadomości, jestem autorem danych SQL.

tjscience
źródło
1

Chciałbym dodać mój głos do chóru odpowiedzi, które mówią „Jest środek!”.

Dla programisty aplikacji SQL jest mieszanką rzeczy, które możesz chcieć kontrolować i rzeczy, których prawie na pewno nie chcesz mieć problemów z kontrolowaniem.

To, czego zawsze chciałem, to warstwa (nazywam to DAL, ORM lub mikro-ORM, nie mam znaczenia, która), która zajmie się całkowicie przewidywalnymi decyzjami (jak przeliterować słowa kluczowe SQL, gdzie idą nawiasy, kiedy wymyślić aliasy kolumn, jakie kolumny utworzyć dla klasy, która zawiera dwa zmiennoprzecinkowe i int ...), pozostawiając mnie odpowiedzialnym za aspekty SQL wyższego poziomu, tj. jak organizować JOIN, obliczenia po stronie serwera, ODLEGŁOŚCI, GROUP BY, podkwerendy skalarne itp.

Więc napisałem coś, co to robi: http://quince-lib.com/

To jest dla C ++: nie wiem, czy to jest język, którego używasz, ale mimo wszystko może być interesujące zobaczyć to spojrzenie na to, jak mógłby wyglądać „środek”.

slyqualin
źródło