Following a Select Statement Through Postgres Internals
patshaughnessy.net
patshaughnessy.net
Just drop sort clause. Returning the user with the lowest id seems like an unusual use case.
Imagine searching for a name in a phone book and only finding the oldest person with that name, or the person with the lowest phone number.
More common cases are checking whether a user exists, which doesn't require a sort, or finding all the users with a particular name, which I guess could be paged using limit and offset.
The reason I used this particular SQL statement as an example is that ActiveRecord (a Ruby ORM) generates it from a fairly simple, common Ruby expression. I suppose ActiveRecord could be improved to drop the sort when you know there's one one possible match.
Perhaps (a) the user doesn't care what ordering is used, and/or (b) (such as in your example in the preceding post) hasn't specified an order (and apparently PK ordering is defaulted to PK - a model option?). It would be error-prone for ORM to take (b) as implying (a).
There are other reasons to use prepared queries but if performance is your only one it may not be worth it unless your query is either very complex, or runs in a tight loop.
Newish versions of Postgres (9.2+ I believe) try to paper over this surprising effect by re-planning queries a few times to check for cost stability before really saving the plan. It has proved very practical.
See http://www.postgresql.org/docs/9.2/static/sql-prepare.html's notes section, reproduced here:
Notes
If a prepared statement is executed enough times, the server may
eventually decide to save and re-use a generic plan rather than
re-planning each time. This will occur immediately if the prepared
statement has no parameters; otherwise it occurs only if the generic
plan appears to be not much more expensive than a plan that depends
on specific parameter values. Typically, a generic plan will be
selected only if the query's performance is estimated to be fairly
insensitive to the specific parameter values supplied.Of course this sort of approach would give up the (debatable) interoperability capabilities of SQL and I'm not sure parsing is enough of a bottleneck for it to really be worthwhile. A "binary SQL" spec would also be interesting (and maybe exists already?).
Not sure if it's exactly what you're getting at, but SQL Server has a "USE PLAN" hint that lets you set the entire query plan (using an XML string).
PostgreSQL's policy is strongly against hints, so we're unlikely to see anything like that in Postgres.
a * b Cross-product / Join if column names match
a + b Union
a(first=="joe" && salary>100000) Select rows
a[first,last,ssno] Select columns / project
I hate SQL syntax and wish relational algebra was used instead.The argument that SQL allows you to say what the result should be without any reference to the order in which the steps should be done is fine, except that it is hard to say some things in SQL. If C compilers can transform sequential, imperative code to an equivalent optimized form, I don't see why relational algebra compilers / optimizers cannot.
Optimal join order usually is a function of both the query and the data, and a query optimizer inside your database doesn't necessarily find the optimal join order. It uses heuristics (which often include particulars about the data currently stored in the database) to find a join order that's hopefully better than a naive query plan, in much the same way that optimization passes in a C compiler use heuristics to generate machine code that's hopefully faster than a naive translation to machine code.
> The argument that SQL allows you to say what the result should be without any reference to the order in which the steps should be done is fine, except that it is hard to say some things in SQL.
The GP is talking about a surface syntax change, not a change in the underlying computation model. Using a relational algebra notation, the query optimizer would have just as much freedom as an SQL query optimizer. Relational algebra isn't any more inherently imperative than SQL is.
> If C compilers can transform sequential, imperative code to an equivalent optimized form, I don't see why relational algebra compilers / optimizers cannot.
It sounds like you want a semantic change that gives the query optimizer less freedom than an SQL query optimizer. The GP is suggesting only a syntactic change. The thing it sounds like you want does sort-of exist... many SQL databases will let you inspect the query plan that their optimizer has generated.
However, it sounds like you want some statically defined query plan. The problem with this is that the optimal plan depends on the data that's in the database at the time the query is run. For instance, a query optimizer can look at a complex query with multiple constant WHERE clauses on indexed columns, and use the indexes to quickly determine the size of intermediate tables when deciding the order in which to perform joins. A query language that statically defines a query plan cannot take advantage of this information, unless you want to "re-compile"/"re-optimize" once a day or something. However, if you trust the database to automatically re-optimize on some schedule, then you've lost your static query plan and it seems you might as well let the query optimizer regenerate the plan based on heuristics created by the database developers rather than sticking to some static schedule of recompilation/reoptimization points.
... and this notation almost seems more similar to the underlying math than SQL does.
It's not there any more - it was replaced with SQL in Postgres95, the predecessor to PostgreSQL.
Indeed, I'm starting to feel like a shill given how often I praise it, but if you have any interest in language implementations and don't mind Ruby as a vehicle for some expiration, check out Pat's book Ruby Under a Microscope.
Looking forward to the next installment. That query is so simple that you're not seeing what a real database can do. Let's see something with a JOIN and lots of indices, so the optimizer can do some work.
But I'm hardly a PG expert.
Excellent article in any event, it's really interesting to see how things work under the hood.
These stats are a huge part of cost-based query optimisation, which all major DBMSs do these days.
Details here: http://www.postgresql.org/docs/9.3/static/planner-stats.html
Postgres will not necessarily do a full external merge sort for the query plan shown in the article: when there is a LIMIT k clause, the Postgres sorting code has optimizations to only keep the top k values in memory and do an in-memory sort (obviously, a full seqscan of the input is still needed without an index). Search for TSS_BOUNDED and tuplesort_set_bound() here:
https://github.com/postgres/postgres/blob/master/src/backend...
Plus I wasn't interested in comparing one DB vs. another, as much as I was interested in understanding how any DB works.