Live data from Hacker News

What ORMs have taught me: just learn SQL (2014)

wozniak.ca

651–654 of 654 posts

Re: What ORMs have taught me: just learn SQL (2014)

#651

Earlier quoted context omitted.

Maybe it's because the problem isn't directly caused by ORMs but just a very poor usage of ORMs. The same problem would have existed if a loop was written to perform the same query.

Sure you can make arguments one way or another regarding if a hand-written block of SQL would have the same flaw, but if an experienced DBA or developer writes it, I would bet on their output way over anything an ORM outputs. If you consider the software development process as a whole, the explicit SQL approach intrinsically guarantees additional scrutiny of the actual SQL statements. If you hide all of this behind a…

Yep: “now you have 2 problems.”

Re: What ORMs have taught me: just learn SQL (2014)

#652
post #644

Earlier quoted context omitted.

Yes, but I'm not sure I get the benefit of decoupling the schema, I'm still coupling to the stored procedure interfaces, and still have to deal with the shape of input and results.

If schema needs to be changed in many cases sp interface will stay the same e.g. I can do changes/optimizations to schema without changing the calling code.

But, if it's a schema change where you have to update the SP, you still have to change code... it's that the code is in (PL/T)SQL vs in another language.. You still have to update code either way.

Re: What ORMs have taught me: just learn SQL (2014)

#653

I'm okay with ORMs, but I can't stand lazy evaluation. It often leads to situations where it's entirely unclear when the program is making a database call. For example, given the small django program: dbcall = models.Purchases.objects.filter(amount = 100) if dbcall: do_something() if len(dbcall) > 5: do_something_else() third_thing(dbcall[0]) Does the above app make 1, 2 or 3 database requests? There is an answer, bu…

>There is an answer, but it's not at all clear to the developer. A cursory reading of the documentation is usually a first step in acclimating to an otherwise unfamiliar system. It just so happens, for your example here, a complete explanation[1] can be found at the very top of what's likely the most vital subsystem's documentation. During due diligence, this information will be among the first encounters. [1] https:…

> A cursory reading of the [django] documentation is usually a first step in acclimating to an otherwise unfamiliar system. It just so happens, for your [lazy evaluation] example here, a complete explanation can be found at the very top ...

The "very top" of the django lazy evaluation documentation you pointed to hardly sheds much light on the issue. The documentation just says that certain operations cause database queries, and that some are cached. It's not clear whether doing two similar operations consecutively will result in two database queries (e.g., checking len(dbquery) twice, or checking for truthiness then pulling the first object from a database query).

The django documentation does differentiate between evaluated and non-evaluated database queries, but to the developer, it's the same object. Would be much better if an "unevaluated query" and an "evaluated query" were two different types with different semantics.

Worse, these lazy evaluation semantics are not terribly pythonic. Checking the length or truthiness of a string, list, set, dict, or tuple is an O(1) operation. Checking the length of a database query may (or may not) make network calls, and may have O(N) performance or worse.

Databases queries can give rise to performance bottlenecks and race conditions, and hiding what's actually happening from the developer is a recipe for all sorts of problems.

Re: What ORMs have taught me: just learn SQL (2014)

#654

Earlier quoted context omitted.

Let's talk about how this works in reality. In ActiveRecord, there's a method called find_by_sql. You can't call it directly; it's a class method on an ActiveRecord model. So you have to choose which of your ActiveRecord models should be used to instantiate the rows of your result set. (What if your result set doesn't really match any of your models? Pick one arbitrarily.) Your SQL has some extra columns. What happen…

You can execute a "non-model" query like so: results = ActiveRecord::Base.connection.execute(sql)

The API docs don’t make it clear whether that’s still possible so I didn’t mention it explicitly, but I have done that before and that’s what I was alluding to with the “array of hash tables” comment.
Post reply on HN