Live data from Hacker News

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

wozniak.ca

161–170 of 354 posts

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

#161

Earlier quoted context omitted.

The correct SQL query will be more performant than what? The correct ORM call will build the same correct SQL query. ORM is ultimately SQL

So there is no CPU cycles for the ORM itself? That’s free?

It's 2026. CPU goes brrr. It's absolutely trivial compared to the query execution time.

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

#162
post #132

The argument that really hits home for me, after 30+ years in this industry, is stored procedures. The “Stored Procedures are Evil” argument to me is an artifact of an industry that promotes treating engineers and infrastructure as entirely interchangeable and anything that gets in the way of that is Evil(tm). But what working at Salesforce in the 2000’s taught me is that you can do really amazing things if you’re wi…

I haven't used stored procedures yet, but even ON DELETE CASCADE is super convenient and I suspect somewhat underused by SQL scaredy cats.

I think the stored procedure equivalent would be a "on delete, cascade these tombstones" -- both safer and cleaner.

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

#163

Earlier quoted context omitted.

AKA making the easy parts easier while making the difficult parts harder.

The difficult parts are just literally a raw SQL string so how is that any harder?

That you somehow have to adapt the results into the same format the ORM uses. And has to adapt the parameters into taking data from the ORM. Or has to split your entire functionality from the ORM so you can actually access the database directly without one part of your code interfering with the others.

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

#164

I don't disagree with any of the major gripes people have with orms and I find SQL to be much cleaner in a lot of circumstances. That being said, if orms didn't force you to explicitly define your domain models about 60% of developers would simply never do it. And you would see differently structured, ad-hoc interfaces defined all over the code base completely entangled with whatever action they are trying to perform…

You shouldn’t use ORM entities as domain models. The domain should not depend on anything from the integration layer (db entities, REST request/ response, etc).

Ideally models are generated from SQL schemas, which you map to domain models.

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

#165
post #85

I wonder if the real problem isn't being able to write efficient queries, but that developers struggle to add (yet another) programming language. Just use AWK, just use SQL, just use jq, just use xyz. It's a lot of overhead. I would be OK to lose whatever fractional speed difference to be able to write my queries in a different scripting language. If I ever scaled so much that I needed to shave microseconds off my qu…

There are rather concrete problems that strictly prevent it from being possible to efficiently map graph (object) database access patterns to a relational database. It's not a matter of "fractional speed difference" unless your database has very few entries. OR mismatch problems often like to appear shortly after your database starts to see any real use. The only performant way to use an ORM is to use escape hatches…

    There are rather concrete problems that strictly prevent it from being possible to efficiently map graph (object) database access patterns to a relational database.
Do you mind going more into that? Naively, it seems like prolog/datalog describe graphs pretty well and they're inherently relational. Relational databases have typically just optimized for row-oriented OLTP uses instead of columnar OLAP, but there's nothing inherent preventing one or the other. They're duals of each other.

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

#166
post #153

Earlier quoted context omitted.

People focus on the query writing aspect of ORMs too much. That's not that primary reason you use an ORM. It's primary purpose is to hydrate objects in the runtime. If I pull a datetime from SQL there's a lot of value in having a single piece of code handle that datetime the same way across the entire stack. I can unit test that handling once across the entire code base. Very few ORMs are aware of how the data is ind…

> I expect someone who uses an ORM to understand SQL well. From experience, I don't. ORMs are usually sold as 'learn this instead of learning SQL'. For many, the ORM creates the tables, alters the tables, and queries the tables; they don't see SQL and they don't know SQL. When that works, it works, but when it falls apart, they have to debug the SQL and the abstraction layer. I'd rather have fewer unnecessary abstrac…

You can always make the ORM Model based on a view. Sometimes a background job compiling a simple result set table is the appropriate answer.

Almost all ORMs boil down their queries down to a single query handler so it's actually super easy to find the query.

My ORM for example:

  *Read paths*

  - Models/Factory/Getters/GetAllRecords.php:28 - table(...) when indexField is set.
  - Models/Factory/Getters/GetAllRecords.php:31 - allRecords(...).
  - Models/Factory/Getters/GetAllRecordsByWhere.php:95 - table(...) when indexField is set.
  - Models/Factory/Getters/GetAllRecordsByWhere.php:98 - allRecords(...).
  - Models/Factory/Getters/GetRecordByWhere.php:20 - oneRecord(...).
  - Models/Factory/Getters/GetByQuery.php:9 - oneRecord(...).
  - Models/Factory/Getters/GetAllByQuery.php:9 - allRecords(...).
  - Models/Factory/Getters/GetTableByQuery.php:9 - table(...).
  - Models/Versioning.php:122 - revision table(...).
  - Models/Versioning.php:124 - revision allRecords(...).

  *Write paths*

  - Models/Events/Save.php:41 - insert on save() for phantom records.
  - Models/Events/Save.php:53 - update on save() for existing dirty records.
  - Models/Events/Delete.php:18 - delete by primary key.
  - Models/Events/Destroy.php:24 - insert history row before destroy for versioned models.
  - Models/Versioning.php:180 - insert history row after versioned save.

  Error/retry path

  - Models/Events/HandleException.php:35 - direct $connection->exec(...) for auto-creating missing tables.
  - Models/Events/HandleException.php:43 - direct $connection->query(...) to rerun the failed query after table creation.

  All of those eventually bottom out in IO/Database/StorageType.php:119 for non-result queries via PDO exec, or IO/Database/StorageType.php:149 for result queries via PDO query.

I used to profile all my queries in those two methods but with tools like NewRelic there's no need to slow the code down with profiling cruft.

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

#167

I don't disagree with any of the major gripes people have with orms and I find SQL to be much cleaner in a lot of circumstances. That being said, if orms didn't force you to explicitly define your domain models about 60% of developers would simply never do it. And you would see differently structured, ad-hoc interfaces defined all over the code base completely entangled with whatever action they are trying to perform…

I understand you mean “data” model instead? Perhaps for simple cruds, there’s no much point in differentiating between the data model and the domain model. For more complex scenarios, having orm concerns leak into the domain model is not nice

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

#168

I don't disagree with any of the major gripes people have with orms and I find SQL to be much cleaner in a lot of circumstances. That being said, if orms didn't force you to explicitly define your domain models about 60% of developers would simply never do it. And you would see differently structured, ad-hoc interfaces defined all over the code base completely entangled with whatever action they are trying to perform…

>ORMs being a forcing function for domain modeling is enough benefit for me that it outweighs all of their obvious limitations.

That was a surprising take!

I know only a few ORM's but it seems they end up just adding another layer of DTO objects that are entirely separate from the domain classes anyway. So best case the ORM is just a detour for a good domain model. Worst case it creates a weird database-contaminated domain model that's hellish to maintain.

So I would't say ORMs force domain modeling, or even help. Are you perhaps thinking of a particular stack where the ORM is just one part of it?

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

#169

I don't disagree with any of the major gripes people have with orms and I find SQL to be much cleaner in a lot of circumstances. That being said, if orms didn't force you to explicitly define your domain models about 60% of developers would simply never do it. And you would see differently structured, ad-hoc interfaces defined all over the code base completely entangled with whatever action they are trying to perform…

Too often, the avoidance of learning SQL creates more work than learning SQL.

One example is starting with NOSQL and proceeding to learn how to make it into a relational database.

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

#170
post #72

I always disliked ActiveRecord, but I figured ORMs don't have to be ActiveRecord. I created this library 14(!) years ago not too long before this article was written https://github.com/iaindooley/PluSQL The idea is that you like SQL, but it gets repetitive writing joins and accessor code. I had always hoped it would catch on as a pattern: no boilerplate, automatic mapping to objects in your code of any query (whether…

That's a query writer. Not an ORM.

No, it's an ORM because it gives you object based iteration over your query (and the ability to use custom classes for those objects, you just don't have to create classes for every single thing if you don't need them).

EDIT: oh wait looks like I never got around to implementing the ability to use custom classes :) this is still in the to do section:

come up with a good "mix in" style to cast the objects returned from the iterator to a new class for implementing custom functionality (that one would normally include as part of the "boilerplate" class)

Post reply on HN