News for hackers. Stuff that matters.
Re:Literate SQL by caseymarquis on Sunday June 25, 2017 @10:33AM (#14630158)
It's critical to have a good understanding of SQL, but once you do, ORMs with a functional syntax solve this problem for many of us. I know it's not possible for some people to use ORMs as they can't risk the ORM making a performance mistake, but I think the solution is to improve ORMs to the point that writing raw SQL is akin to writing assembly instead of using a higher level language.

That said, we're not there yet. Using an ORM in 2017 without understanding what SQL you want it to produce IS NOT OKAY. Please learn SQL if you're going to use an ORM, and understand the SQL you are producing with the ORM.

Summed up, if you can, use an ORM to solve this problem.

Re:Literate SQL by gregmac on Sunday June 25, 2017 @12:56PM (#14630930)
I disagree about SQL being like assembly. It's a fairly high level language, because underneath the engine is figuring out how to use indexes and actually run your query. If you want to draw parallels, ORMs are more like writing code in a template language that's written in the language you're actually working in.

I've spent far too much time fighting with ORMs trying to get the SQL I want generated. Additionally for complex queries, I often develop in a SQL manager interface, because it's so much more direct. When I'm done, I have a working SQL query - I can paste it in to my code and parameterize it, why should I spend even more time fiddling with an orm?

I like "micro ORMs" that just map rows to objects. Generating INSERT and UPDATE statements is ok, and single table selects with a single where clause are sometimes ok. Beyond that, I'd rather just skip the middleman.

That said, for small databases (a GB or two) that are reasonably well designed (e.g. 3NF), the speed of current I/O and optimization engines in databases is such that even the worst SQL will generally run fine - so if you find it faster to use ORM and understand the future pitfalls, go for it.

Re:Literate SQL by paulddraper on Sunday June 25, 2017 @02:04PM (#14631276)
Agreed. If anything SQL is declarative and more high level than most application code.

FYI, if you have a 1-2GB database, that whole sucker fits in RAM, so rejoice.

Re:Literate SQL by koolba on Sunday June 25, 2017 @09:50PM (#14633462)
1-2 GB? You can have a 1 TB fit into RAM these days. (And many of us do!)
Re:Literate SQL by threeseed on Sunday June 25, 2017 @06:46PM (#14632653)
Actually more often than not ORMs are going to provide better performance than having people inexperienced with SQL writing it themselves. Especially when it comes to batching, pagination and joins and the intelligent use of in memory caching rather than doing everything in database.

And the biggest advantage of an ORM is that you can trivially switch between databases which is often required for running automated tests. SQLite or H2 for development and then Oracle, SQL Server or Teradata for production is a very common pattern I've seen at many companies.

Re:Literate SQL by felixge on Monday June 26, 2017 @02:55AM (#14634633)
Running your tests against a different DB than what you're using is an anti-pattern IMO. You'll not be able to trust the results, and you'll be limited to the lowest common denominator of the databases your using.
Re:Literate SQL by oweiler on Tuesday June 27, 2017 @11:34AM (#14646342)
This so much! Furthermore any application of reasonable size will make use of database-specific functionality.
Re:Literate SQL by gfody on Sunday June 25, 2017 @02:42PM (#14631462)
I've found views, parameterized-views/table-valued-functions can be a nice compromise to keeping the SQL relatively simple and thus ORM friendly without sacrificing performance.
Re:Literate SQL by weavie on Sunday June 25, 2017 @03:25PM (#14631683)
This can be dangerous if over used. It can be very tempting to quickly pull in a 'left join blah' to grab some fields you may need. But that blah view could be hiding some massive performance sapping beast.

When it comes to optimizing a slow running query, having to step through layer after layer of nested view can be incredibly challenging.

Re:Literate SQL by gfody on Sunday June 25, 2017 @05:14PM (#14632224)
I can't speak for other engines but at least SQL Server and Oracle will eliminate unnecessary joins for inlined table-valued functions, e.g.:

create function thing (a, b) returns table as select * from table_1 left join table_2 on ...

select (only cols from table 1) from thing(a, b)

..and table_2 is not accessed

predicates from the topmost query will be pushed down to the function's query as well so the functions performance is generally equivalent to the adhoc version.

on the whole I find this strategy to be very effective at reducing the complexity of adhoc queries without performance penalties. in the case of indexed views it can greatly improve performance.

Re:Literate SQL by gregmac on Sunday June 25, 2017 @04:29PM (#14631991)
Worse, someone is using the view (that joins several tables) in a join to get one extra field, which would be a simple single join -- they just didn't bother to check where it came from because 95% of the time that view gets used, and no one questions it. I've seen it happen more than once.
Re:Literate SQL by PeterisP on Sunday June 25, 2017 @07:15PM (#14632778)
Why would that be a problem?

Unless you're fetching all the unneeded fields as well, in any decent DBMS both approaches would result in the exact same execution plan with the exact same performance, the unneeded parts/joins of the view wouldn't be executed.

Re:Literate SQL by paulddraper on Sunday June 25, 2017 @11:31AM (#14630446)
I see this opinion a lot.

I don't quite understand it. Your DBMS isn't some ambivalent data store with simple universal semantics.

I'm not just talking about SQL features like complex subselects or CTEs, but index hints, lock order, transactional visibility, non-trivial column constraints, index locks...

These matter in appreciably sized public-facing (e.g. web) systems. Granted, with enough transactions and roundtrips to application logic, an ORM can mimic these.

Now, I do know YAGNI; you might never get to a scale where an ORM poses a limitation.

I just suppose I don't see large enough benefits of learning and using an ORM in the early stages, to outweigh the cost of switching to SQL in the (admittedly hypothetical) later stages.

Re:Literate SQL by richardlblair on Sunday June 25, 2017 @11:50AM (#14630568)
I think your post makes a lot of assumptions. I do not believe scale to be a reason not to use an ORM. If you pay attention to what you're doing you can scale a system that uses an ORM just fine.

The orm is usually not the problem, it's usually that people don't know what they are doing and introduce serious performance issues.

Re:Literate SQL by tfigment on Sunday June 25, 2017 @12:32PM (#14630801)
My db issues for last ten years have frequently been a mix of bad query plans and terrible orm layers. Doctrine in Symfony rarely yield good queries in mysql for us. We've been moving away from orm where possible because we don't need to support multiple databases. Further if I switch my db to postgres I'm changing out everything else anyway to remove php from the codebase. I didn't write the original code but my team has to maintain it. The orm makes that hard actually compared to staight sql in the end.
Re:Literate SQL by weberc2 on Sunday June 25, 2017 @01:50PM (#14631214)
As I understand it, the point of an ORM is to make relational data look and feel more like the objects in my program; I shouldn't have to think about the consequences of my data living on the other side of a network connection. Even if that isn't the official point, it's at least a widely-held misunderstanding. If you're going to write code that uses the ORM this way, you're going to have a bad time, but if you write your code intelligently, you end up using your ORM as a glorified query builder.

I think an ORM makes more sense in a functional language since the interfaces are more likely to be declarative than imperative. For example, an in-memory List and a SQLQuery can both implement a filter() method that takes a function and applies it in the way most efficient to that data structure; in traditional OO languages, we usually loop over our in-memory structures explicitly, and doing that with a database is prohibitive.

Re:Literate SQL by weberc2 on Sunday June 25, 2017 @01:38PM (#14631158)
While I prefer vanilla SQL to the current generation of ORMs, I think ORMs are trying to address a real problem--namely that SQL (despite being high level) isn't very abstraction-friendly. Abstractions in SQL can be expensive and often unpredictably so, despite how clever databases are today. I think part of the problem is the mismatch between the largely imperative OO paradigm and the largely declarative relational paradigm, but I suspect that there's some semantic impedance between SQL and a truly relational model which contributes to the problem.
Re:Literate SQL by DaiPlusPlus on Sunday June 25, 2017 @05:28PM (#14632294)
I advocate ORM use for guaranteed type-safety - so long as SQL queries are processed as strings inside your application there's always the risk of column names and types not matching your entity classes - by using an ORM that generates SQL based on your classes (e.g. Entity Framework with Linq) it promotes mismatches to compile-time errors. This alone makes it worthwhile.
Re:Literate SQL by weberc2 on Sunday June 25, 2017 @07:02PM (#14632712)
How does an ORM know what your database schema is at compile time? Honest question.
Re:Literate SQL by mikaelhardo on Monday June 26, 2017 @04:50AM (#14635134)
You either generate a model based on your database, or generate your database from your model. That way the database and model are always in sync and you get errors in the code. In Entity Framework this is called either "Code first" or "Database first"
Re:Literate SQL by Asooka on Sunday June 25, 2017 @12:50PM (#14630888)
The reason for me to use ORM rather than direct SQL queries is so I can keep everything written in a single language, so I can develop with one IDE. Having everything under one roof is a huge boon to productivity, rather than having to edit the logic in the IDE, then edit the database queries in a different editor, and the two knowing nothing about each other. It lets me directly map my source language's type system to the database's schema, avoiding discrepancies.
Re:Literate SQL by wvenable on Sunday June 25, 2017 @01:10PM (#14631005)
Don't most IDE's do SQL in the mix with everything else or am I just spoiled by Visual Studio?

My opinion is that one uses an ORM for different situations than they would use SQL. Many applications can use an ORM and nothing else. Some can use an ORM for basic CRUD tasks and then raw SQL to do analysis or reporting.

Re:Literate SQL by gfody on Sunday June 25, 2017 @02:50PM (#14631499)
you (and I) are absolutely spoiled by Visual Studio w/SSDT. there is nothing even remotely close to that level of integration for database development in other stacks.
Re:Literate SQL by justinclift on Sunday June 25, 2017 @04:01PM (#14631862)
Err... any of the JetBrains IDE's? They have database integration.

It's also available standalone as "DataGrip", though I've never used it:

https://www.jetbrains.com/datagrip/

Re:Literate SQL by gfody on Sunday June 25, 2017 @05:05PM (#14632185)
the level of integration with SSDT is way beyond that - the database structure and stored procs live side-by-side with your code, are source controlled together, built and deployed together. there's compile-time checks for stored procedures, code analysis, etc. DataGrip is just an alternative for SQL Developer/Management Studio, SSDT is much more.
Re:Literate SQL by paulddraper on Sunday June 25, 2017 @01:02PM (#14630955)
I can sympathize.

For me, that's Scala JVM on the server, ScalaTags/ScalaCSS/ScalaJS in the web browser, Slick for the ORM, and SBT for the build system. The bliss of learn once, program anywhere.

When this hits reality though, I use Relate https://github.com/lucidsoftware/relate (disclaimer: I'm a contributor)

It's SQL, but with minimal syntactic overhead.

    sql"SELECT * FROM users WHERE email IN ($emails)".asList[User]()
Re:Literate SQL by Nullabillity on Sunday June 25, 2017 @02:07PM (#14631293)
Since you're already using Slick, what's the difference between Relate and Slick's native SQL literals[1]?

[1]: http://slick.lightbend.com/doc/3.2.0/sql.html

Re:Literate SQL by paulddraper on Sunday June 25, 2017 @03:02PM (#14631557)
Or Anorm [1] for that matter. They're all pretty similar in the idea of typed Scala string interpolation.

[1]: https://www.playframework.com/documentation/2.5.x/ScalaAnorm...

Re:Literate SQL by zzzeek on Sunday June 25, 2017 @10:49AM (#14630232)
You can have functional SQL query languages that map directly to SQL without object oriented row mapping. Everyone can use these tools without performance issues.

Disclaimer: i wrote SQLAlchemy.

Re:Literate SQL by mshenfield on Sunday June 25, 2017 @11:19AM (#14630378)
> You can have functional SQL query languages that map directly to SQL without object oriented row mapping.

Well said. I always think of this as the canonical example:

http://sqlkorma.com/

I don't know what rock I've been under, but didn't realize SQLAlchemy had the same idea w/ SQLAlchemy Core.

Re:Literate SQL by Dangeranger on Sunday June 25, 2017 @12:52PM (#14630901)
Another excellent example of this is Elixir's Ecto library for composing SQL from modular fragments https://github.com/elixir-ecto/ecto/blob/master/README.md
Re:Literate SQL by virtualwhys on Sunday June 25, 2017 @02:37PM (#14631424)
> without object oriented row mapping

Korma seems to do exactly that, N+1 lazy loaded queries included. SQLAlchemy, Esqueleto, Slick, Quill, and the like all generate precisely what you tell them to (i.e. queries semantically the same as what you'd write by hand).

This is not to disparage Korma, it looks pretty cool, I'd certainly give it a look if I worked with Clojure.

Re:Literate SQL by nerdponx on Sunday June 25, 2017 @11:03AM (#14630287)
Is that really a disclaimer, or just the source for your claim?

I'm sure you know this, but there are actually several "query builder" tools out there for Python, including SQLAlchemy Core. I'd love to see a side-by-side comparison.

Re:Literate SQL by lobster_johnson on Sunday June 25, 2017 @01:21PM (#14631054)
He probably meant "disclosure", not "disclaimer".
Re:Literate SQL by zzzeek on Sunday June 25, 2017 @01:32PM (#14631123)
The overlords of HN have deemed my post is too old for an "edit" button so, yes, my use of "disclaimer" is a case of auditory familiarity overruling accurate terminology
Re:Literate SQL by nerdponx on Sunday June 25, 2017 @02:49PM (#14631493)
Sorry, it was just my half-assed attempt at flattery anyway ;)
Re:Literate SQL by mshenfield on Sunday June 25, 2017 @10:53AM (#14630251)
Agreed. The ORM vs raw SQL debate is endless, but I prefer using some kind of ORM-y thing when I need to interact with a relational database from a program.

There are still cases where you might build a collection of raw queries (think business analysis using Hive/Impala/Spark SQL). I think it's important to approach it the same way you would a normal program: how can I make my intention clear, how can I verify it works as I expect, how can I reuse without reducing clarity.

Also, just a little joke: https://i.imgflip.com/1rhhzl.jpg

Re:Literate SQL by weberc2 on Monday June 26, 2017 @09:08AM (#14636447)
Query builders are a sort of middle ground between raw SQL and ORMs. They give you database agnosticism and help to prevent syntax errors, etc, especially if your language is statically typed. But they also allow you control over the query performance.
Re:Literate SQL by vinceguidry on Sunday June 25, 2017 @10:43AM (#14630212)
For anybody on Rails, you can call .to_sql on any ActiveRecord::Relation and it will return the exact SQL string that your code is producing. Really handy for troubleshooting, especially for associations.
Re:Literate SQL by meditationapp on Sunday June 25, 2017 @02:13PM (#14631328)
Of course, not all operations return a relation, such as count, update_all, delete, etc, even if they have a sql equivalent.
Re:Literate SQL by lucio on Sunday June 25, 2017 @02:17PM (#14631344)
>but I think the solution is to improve ORMs

http://blogs.tedneward.com/post/the-vietnam-of-computer-scie...

Not trying to attack you, just a cautionary tale that you should read

Re:Literate SQL by enjoiful on Sunday June 25, 2017 @11:10AM (#14630326)
I love Django -- but what it does is mostly magic to me. That being said... I'm fairly competent in being effective in Django -- although not for advanced and efficient querying.

I want to get strong in SQL -- where/how do I start?

Re:Literate SQL by collyw on Sunday June 25, 2017 @01:04PM (#14630971)
Practice would be my advice.

First thing to do would be to start printing the queries generated by the ORM to see what it is doing (though it produces some fairly verbose SQL, but its usually easy enough to understand).

Then when you are asked to get some one off numbers out of the database try doing it in SQL. In one query.

Its usually possible but takes a different way of thinking - in sets. Build up queries gradually. Start with the main table. Join in the next table and see the results. Add some conditions in your where clause or join conditions. See what the result is and how it changes.

As for thinking in sets, that is easily said but difficult to translate into words.

I guess describing the set of data that you want back from the database is a good start. My previous team leader would always describe the results in terms of "if x then y" (imperative thinking). When you are find yourself doing that, instead try to describe the data without the "if" statements and instead describe it as "the set where condition x and y are met". That will get you halfway there. Once you start thinking like that you will start to see the beauty in the relational model.

I was a good few years into my career before I started thinking this way - now I try to do as much work in the database as possible - it avoids a whole categories of bugs, usually keeps your code shorter and is one of the easiest ways to improve performance.

Re:Literate SQL by AlisdairO on Sunday June 25, 2017 @12:46PM (#14630872)
[self plug] Take a look at https://pgexercises.com/ . It's a learn-by-doing set of SQL exercises. Focused on Postgres, but the large majority is standard SQL.
Re:Literate SQL by 3131s on Sunday June 25, 2017 @01:01PM (#14630948)
Write raw SQL queries. My feeling on the Django ORM is that it's useful for defining models and managing migrations, but I prefer to write raw SQL for all queries.

The PostgreSQL documentation is really good too.

Re:Literate SQL by ubernostrum on Monday June 26, 2017 @01:00AM (#14634203)
Meh. My feeling is that Django and other web frameworks are too magical -- I always worry they might be doing something inefficient. That's why I write all my web applications in hand-tuned assembly. It even has reusable abstractions for when I need them, and nice hand-formatted assembly is super readable!
Re:Literate SQL by 3131s on Monday June 26, 2017 @10:31AM (#14637077)
You're seriously comparing SQL to assembly? There's a point where it doesn't make sense to add another layer, another dependency, etc.
Re:Literate SQL by ubernostrum on Monday June 26, 2017 @11:09AM (#14637391)
In both the "never use an ORM" and "always use assembly" cases, the argument is based entirely on having full control of what's going on and not trusting any intermediate layer to get it right or eke out every last femtosecond worth of performance.

So it's a perfectly fair comparison.

Re:Literate SQL by collyw on Sunday June 25, 2017 @01:09PM (#14631002)
The ORM takes a whole lot of pain out of updates as well.

Filtering also work fairly nicely for simple stuff, as putting conditions in a dictionary and passing it to filter(kwargs) is a lot nicer than messing about with SQL strings.

I agree that the ORM is limited if you want moderately complex queries though.

Re:Literate SQL by Daishiman on Sunday June 25, 2017 @04:56PM (#14632131)
> but I prefer to write raw SQL for all queries.

If you're doing this you're missing out on the biggest advantage of the ORM, which is that it allows you to compose queries.

Using the Q objects, query expressions, and custom Queryset objects, you can filter objects by pretty much every imaginable criteria out there. This would be horrendously difficult and error-prone writing plain SQL.

The Django ORM, despite having limitations if you want to run analytics (and that's really a use case for with plain SQL excels), generally writes out exactly the same SQL I'd write by hand.

Re:Literate SQL by 3131s on Sunday June 25, 2017 @11:09PM (#14633780)
> This would be horrendously difficult and error-prone writing plain SQL.

I do it all the time :) I love looking at long SQL queries that are formatted nicely and use good naming conventions.

It's also part of a more general philosophy I have of reducing dependencies whenever possible. With Django it makes sense to use the ORM wherever it suits you, since it's already built in, but there are times when you need to know raw SQL anyway (e.g. try populating a large database without COPY, only using the Django ORM).

Re:Literate SQL by combatentropy on Sunday June 25, 2017 @04:36PM (#14632023)
> I want to get strong in SQL -- where/how do I start?

1. I suggest the PostgreSQL documentation itself (https://www.postgresql.org/docs/current/static/). It's well-written, but still wordier than need be, and if you try to read it from start to finish, you will probably die. However, the beginning chapters are overviews of SQL. Once you feel in the mud, you are probably in very specific, technical chapters. You can just skim these, jump to ones that interest you at the moment, etc.

2. There also a separate wiki (https://wiki.postgresql.org/wiki/Main_Page). I haven't gone there much, but it is a nice complement. It has practical summaries of things that the main documentation spins out of control (like setting up replication). It also has some examples of how to to do really advanced things in SQL.

3. A well-reviewed, short book. The first book I read was SQL Demystified. It's a short and easy intro to SQL in general. Find something like that. I have tried hard to find good books on SQL, but most are huge tomes that will crush your soul.

4. Practice. For the past decade at my job I have been forced to learn complex SQL for various business reports, across a variety of tables. And I still feel like an intermediate.

Re:Literate SQL by NumberCruncher on Sunday June 25, 2017 @11:50AM (#14630567)
I used w3schools for learning webdev related things but their SQL tutorial seems to be good as well.

[1] https://www.w3schools.com/sql/default.asp

Re:Literate SQL by wesd on Sunday June 25, 2017 @11:38AM (#14630479)
Start by having a strong understanding the various joins first: http://www.sql-join.com/sql-join-types/
Re:Literate SQL by walshemj on Sunday June 25, 2017 @12:29PM (#14630788)
If you can get an employer to pay for it the Into course that Oracle does is fairly good it certainly got me up to speed to be able to work on an oracle project.
Re:Literate SQL by weberc2 on Sunday June 25, 2017 @01:21PM (#14631060)
I think the solution is to upgrade SQL the language. There's a very low complexity threshold after which you have to trade readability/composability for decent performance (in other words, there are a lot of cases where a human can notice a permissible optimization, but a database can't because it might break correctness for some odd edge case). We're solving that problem with programming languages (notably Rust); I'm not convinced that there's something inherently different about relational databases.
Re:Literate SQL by lgas on Sunday June 25, 2017 @02:52PM (#14631510)
Project M36 is a database that implements a relational model and corresponding query language (TutorialD) based on (among other things) the ideas from Date and Darwen's Third Manifesto. TutorialD solves many of the problems present in SQL, especially around composability.

https://github.com/agentm/project-m36

Re:Literate SQL by weberc2 on Sunday June 25, 2017 @07:06PM (#14632732)
I've heard of tutorial D before, but I haven't taken the time to learn it as I'm off the impression it isn't widely deployed. :( I'd love to hear any first hand experiences though!
Re:Literate SQL by NumberCruncher on Sunday June 25, 2017 @11:37AM (#14630475)
Even if you work with an ORM instead of writing raw SQL you should know when single row processing is OK and when bulk load / data set processing is a must.

My last employer lost 5M+ euros (not reveue but profit) every month because of excessive use of PL/SQL single row processing.

Re:Literate SQL by mistermann on Sunday June 25, 2017 @12:02PM (#14630633)
How could they lose that much $ due to single row processing? Having to buy that much more processing power?
Re:Literate SQL by throwaway91111 on Sunday June 25, 2017 @08:16PM (#14633011)
Some ORM patterns are great, others suck. For instance, the activerecord lifecycle callbacks can be very difficult to maintain and reason about, particularly after_commit hooks and transactions that create associations.
Re:Literate SQL by vladsanchez on Sunday June 25, 2017 @03:17PM (#14631637)
ORMs are for people who don't know SQL.
Re:Literate SQL by specialist on Sunday June 25, 2017 @03:49PM (#14631813)
...yet.
Re:Literate SQL by Daishiman on Sunday June 25, 2017 @04:54PM (#14632120)
SQL is for people whose problem domain is so simple that they don't need to do things such as, I dunno, compose queries.
Re:Literate SQL by flukus on Sunday June 25, 2017 @08:41PM (#14633121)
I agree, but all too often composable queries are for people that don't know who their users are or what the want. If you build workflow centric UI's then the need for composable queries generally goes away.