Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

ORMs are really only useful for throwaway projects and beginners. I have yet to see one without serious downsides in both performance and speed of development, something that they are touted to improve but actually make worse. The ORM I'm stuck with now (Doctrine2) adds a 10x overhead to queries. For the most part, we don't even bother optimizing queries in such situations because why waste time on something that could at most improve performance by 1/10th? The real fix is to get rid of the ORM. That requires a rewrite of two apps that have been in development for four years each. I can't think of a worse architectural decision for business (CRUD) software than using an ORM. Irreversible and forever fucked.


Don't know much about Doctrine2, but that sounds pretty terrible. I'm sorry you are forced to work with something so inefficient.

I've been building apps with Django and Django's ORM for the last 10 years and found essentially zero overhead in most cases. Every once in a while there's a slow page, I open up the debug toolbar which shows me every SQL query that was used to generate the page in a nice waterfall diagram, I see something a little odd and change the order of some filters or add a `select_related`, or `prefetch_related` or discover that some third party library is making a dumb call (unavoidable problem of using third party libraries on any platform) and find a workaround for that. Every once in a blue moon, it appears easier to write a raw SQL statement than figure out what needs to be done to get the ORM to generate it, so I do that. Of course, Django's ORM makes it stupid easy to use a raw SQL statement: https://docs.djangoproject.com/en/2.0/topics/db/sql/

I've worked with a few other ORMs in Python and other languages over the years as well (in Go, Erlang, Elixir, Clojure, nodejs) and never really encountered any where the ORM had a noticeable performance overhead (dominated by the network latency back and forth from the database) and I've yet to work with one that I couldn't just do a raw query when needed. The closest I've seen is when I started using GORM in Go, I found it running slowly and discovered that it automatically adds a "soft delete" functionality so every query gets an additional "and not is_deleted" clause added. Disabled that feature and it was fine. That was my own fault though for starting to build before I finished reading the documentation, as it was pretty clearly explained in a later section. (OK, also the ORMs I was using in Perl and Java back in the late 90's/early 00's were also pretty terrible, but those were prehistoric times.)

You always have to be careful of N+1 problems, but that's not just an ORM thing. You run into that as soon as you have any abstraction in your code. Once you have refactored to `get_list_of_items(some criteria)` and `get_item_details(item)` functions/methods/whatever, whether it is using an ORM underneath or raw SQL, developers working on the app have to know that they can't loop over the results of the first and call the second on each of them. Tradeoffs between reusability and performance are nothing new though and not at all specific to web applications or ORMs.


PHP's concurrency model poses unique challenges to orms but in this case, it's just slow hydration that is the main culprit and that can happen in any language, especially interpreted ones. It's no longer just fetching data and displaying it but fetching, processing (in a slow interpreted language) and then displaying it.

That is one issue. I find the interface the orm provides to also be inferior in every way compared to sql so I just don't get why people would add something that provides even the tiny overhead you describe to get an inferior interface for dealing with the database. Some orms I've used create their own sql like language, so now there is something new to learn (that's useless outside the orm) that provides nothing over actual sql but has all the drawbacks of the orm and sql. Even working with simple objects and queries is more difficult as I hardly know what the orm is doing. When I do look at what it generates, it's always been atrocious in the orms I've used. In addition, trying to wrap my mind around the concepts the orm builds poorly on top of the relational database is truly angering. Taking a wonderful interface to a database and turning it into a set of nonsensical object relationships actually makes it more difficult and more time consuming to write the app with the orm. This is unnecessary complexity for complexity's sake, something proponents of simplicity avoid.

So my experience has not only been that of horrible performance but also that of a horrible ui that slows development to a crawl and creates apps that need to be rewritten to work properly, the exact opposite of what orm proponents claim. One of the main reasons I want to move to a functional language is that orms don't exist there.


I use Doctrine2 in a number of applications. I have a love/hate relationship with it (mostly through fitting it to legacy database schemas) but it's not slow to put/retrieve data from the database. What's slower is the object mapping (hydration); and if you map database rows and relations into objects yourself then your overhead is going to be similar, just labelled as 'application' overhead rather than 'ORM' overhead.

The 10x slowdown I noticed was moving from native database functions (PHP's PDO or MySQLi extensions) to Doctrine2's underlying database abstraction layer, DBAL. Doing a prepared query (with the same SQL) in the native extension was 10x faster than DBAL, which uses the native extension under the wrapper. I never got to why - DBAL is doing more (fair enough) but not enough for this amount of slowdown.


The only way manual processing of the data from the db could take as long as doctrine hydration is if it's written poorly. An app developer who knows how to write apps properly would never do hydration or any of the stupidity doctrine does. Why would one map database rows into objects in the first place? I've rewritten huge swaths of one of our doctrine apps getting a roughly 5x to 10x improvement in speed and I left a lot of optimizations on the table while still providing a general purpose serializer that uses doctrine's meta data behind the scenes.

As for dbal, I think the overhead is in statement preparation and parameter expansion (for array params) and it can be avoided by using the native functions, though that overhead was never 10x for me.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: