Joins 13 Ways
justinjaffray.com
justinjaffray.com
CREATE TABLE Dim_X (
int EntityId
float Value
)
Establishing a point in space for a given entity (regardless of how you derive that ID) is then a matter of: SELECT Dim_X.Value AS X, Dim_Y.Value as Y, Dim_Z.Value as Z
FROM Dim_X, Dim_Y, Dim_Z
WHERE Dim_X.EntityId = Dim_Y.EntityId --Join 1
AND Dim_Y.EntityId = Dim_Z.EntityId --Join 2
AND Dim_X.EntityId = @MyEntityId --The entity we want to find the 3D location of
You will note that there are 2 inner joins used in this example. That is the bare minimum needed to construct a 3 dimensional space. Think about taking 3 cards and taping them together with 2 pieces of rigid metal tape. You can make a good corner of a cube, even if it's a bit floppy on one edge. Gravity doesn't apply inside the RDBMS, so this works out.This same reasoning can be extrapolated to higher, non-spatial dimensions. Think about adding time into that mix. In order to find an entity, you also now need to perform an inner join on that dimension and constrain on a specific time value. If you join but fail to constrain on a specific time, then you get a happy, comprehensive report of all the places an entity was over time.
The other join types are really minor variations on these themes once you have a deep conceptual grasp (i.e. can "rotate" the schema in your mind).
Playing around with some toy examples can do wonders for understanding. I sometimes find myself going back to the cartesian coordinate example when stuck trying to weld together 10+ dimensions in a real-world business situation.
But yes, OLAP.
CREATE TABLE EntityPosition (
int EntityId,
float X,
float y,
float z
)
It does remind me of data warehouse stuff though, given we're working with aggregates and piecing together bits of various dimensions.Well, yeah - it’s an example to get the point across, not an exercise in finding the right level of normalization.
Why use `JOIN` (and `INNER JOIN` and friends) at all when you can write the exact join more accurately IMO with WHERE clauses (and using "*=" operators), and then just list all the tables in the FROM clause?
My brain always hurts trying to parse complex FROM clauses with various JOINs whereas reading the equivalent equations in WHERE clauses is way more straightforward to me.
https://en.m.wikipedia.org/wiki/Relational_algebra
("The result of the natural join [R ⋈ S] is the set of all combinations of tuples in R and S that are equal on their common attribute names... it is the relational counterpart of the logical AND operator.")
⋈ amounts to a Cartesian product with a predicate that throws out the rows that shouldn't be in the result. Lots of SQL makes sense if you think of joins this way.
Boxing all that up into the Cartesian product is a really useful concept, and the whole idea of relational algebra is to find convenient formalisms for relational operations, so it seems like it deserves a separate mention.
The whole relational model clicked for me a whole lot more once I started thinking of each tuple as factual propositions (customer a's name is X, phone number is Y), and then all the operations in the relational algebra start to look more like "how would it be best to ask questions about this subject?"... "I'm interested in facts about..."
I passed on the set understanding where it explained an unintuitive SQL behavior and I hope it helped 'em.
If we are in a pedantic mood, also, a relational-tuple is not exactly the same as a mathematical tuple, relational tuples take different forms depending on who's system you are following (e.g. whether the fields are ordered or not).
Google is spammed with _usage_.
Anybody has some recommendations at hand?
ps. the only one I found was CMU's Database Group resources, which are great
You could try your query on a different search engine. I've had good luck with kagi.
You might want to look into academic papers, e.g., T. Neumann, Efficiently Compiling Efficient Query Plans for Modern Hardware, in VLDB, 2011 https://www.vldb.org/pvldb/vol4/p539-neumann.pdf
https://www.postgresql.org/docs/current/planner-optimizer.ht...
"Building Query Compilers"
https://pi3.informatik.uni-mannheim.de/~moer/querycompiler.p...
EDIT: You also might get use out of TUM's course "Database Systems on Modern CPU Architectures"
The year that contains all the video lectures is 2020:
IMO it's great if you want a holistic view of building a query engine start-to-finish with just enough detail to build a basic implementation.
I probably learned more from the ~100 pages in this book than I did from most other sources.
The best join optimizer paper I know of is still the original Selinger paper (https://courses.cs.duke.edu/compsci516/cps216/spring03/paper...). It doesn't support outer joins and there are more efficient techniques by now, but anyone looking at a System R-like optimizer can read this and feel right at home. (There is also the Volcano/Cascades school of optimizers, which is rather different from System R, but I've found even less information on it.)
As others have said, Postgres' source and documentation is good. In particular, src/backend/optimizer/README contains a number of interesting things that you won't find a lot of other places. (The Postgres optimizer doesn't always use the latest fancy designs, but it's generally very polished and pretty easy to read.)
I can also echo Andy Pavlo's courses (at CMU), they're pretty much the only ones who will explain this stuff to you online. The “Building Query Compilers” PDF is rather incomplete and there's a lot of stuff I never cared for in there, but it contains several key papers from Moerkotte et al if you actually want to implement the modern stuff (DPhyp etc.). In general, most of the modern System R-like stuff (how to efficiently deal with outer joins, how to deal with interesting orders, how to deal with large queries) comes from the groups of Moerkotte and/or Neumann; all of these things had solutions before them, but less efficient and/or powerful and/or elegant.
Finding an applicable index isn't hard (you generally just try to see if it hits a predicate—a so-called “sargable predicate”, for SARG = Search ARGument). Estimating selectivity is hard. Estimating selectivity through joins is perhaps the hardest problem in optimizers, and nobody has truly solved it. This was one of the things I never really got to; there are so many hard subproblems. Like, for something that sounds really simple but isn't, what do you do if you have predicates A=x AND B=y AND C=z and you happen to have indexes on (A,B) and (B,C) (with selectivity/cardinality information) and want a selectivity for all three combined? There are papers that literally require you to build a “second-order cone programming” solver to solve this problem :-)
It means instead of joining tables two at a time and dealing with the temporary results along the way (eating memory), you join 3 or more tables together without the temporary results.
There is a blog post and short video of this on https://relational.ai/blog/dovetail-join and the original paper is on https://dl.acm.org/doi/pdf/10.1145/3180143
I work for RelationalAI, we and about 4 other new database companies are bringing these new join algorithms to market after ten years in academia.
The worst case bounds don't tighten over (stateless/streaming) WCOJ's, but much real world data has far smaller box certificates.
One thing I didn't see is whether Dovetail join allows recursive queries (i.e., arbitrary datalog with a designated output relation, and the user having no concern about what the engine does with all the intermediate relations mentioned in the bundle of horn clauses that make up this datalog query).
Do you happen to know if it supports such queries?
https://justinjaffray.com/a-gentle-ish-introduction-to-worst...
Also, while what you say is true in general for modern DB's, there are some implementations like old Oracle versions where the only way to create the effect of an inner join was in terms of a Cartesian product.
> The correct way to do this is to normalize the table
This is true for transactional dbs, but in data warehouses it's widely accepted that some degree of denormalization is the way to go
Simple realization. Big payoff
However I keep an unique index on the string value and more importantly point integrity constraints to it, mainly for readability. It's way easier to read a table full of meaningful strings rather than full of numerical id or uuids.
This is admittedly a bit pedantic, but in E.F. Codd's original paper, he defined "relation" as the relation between a tuple (table row) and an attribute (table column) in a single table - https://en.wikipedia.org/wiki/Relation_(database). I'm not sure of the author's intent, but the user table example (user, country_id ) might imply the relationship between the user table and the country table. It's a common misconception about what "relational" means, but tbh I'm fine with that since it makes more sense to the average developer.
If you ever need to join sets of data in code, don't use nested loops - O(n^2). Use a map / dictionary. It's one of the few things I picked up doing Leetcode problems that I've actually needed to apply irl.
If it's presorted by the join variable then rolling the loop is faster. Also, if the index is too big for memory, then it might be faster to loop.
My comment was a not very well fleshed out tangential remark on the value of practicing DS&A problems. I know a lot of devs hate Leetcode style interviews. I get it. It's not fun. But contrary to what some people say, I have run into a fair number of situations where the practice helped me implement more efficient solutions.
https://benjiweber.co.uk/blog/2021/03/21/thinking-in-questio....
Edit: Why did I get down voted? :)
Even wikipedia uses a Venn diagram to explain JOIN https://en.wikipedia.org/wiki/Join_(SQL) .
Not trying to use an argument from authority but just pointing out that this is not unheard of.
People can form different mental models of the same abstraction so I see what you are saying
I've never seen it that way because "Venn diagrams do not generally contain information on the relative or absolute sizes (cardinality) of sets." (see https://en.wikipedia.org/wiki/Venn_diagram).
https://blog.jooq.org/say-no-to-venn-diagrams-when-explainin...
And more meta, it is an innocent slightly incorrect statement, stuff like that should not be down voted, reply with a correction. Save down votes for outright malicious posts.
https://blog.codinghorror.com/a-visual-explanation-of-sql-jo...
Like (only intuitively sofar...)
A group by from A rows to B rows - is a map-reduce job - is an AxB linear transformation matrix from your linear algebra course - is...
https://www.cs.cornell.edu/courses/cs3110/2011sp/Lectures/le...
And under "A join is a…join", there's a typo in the partial order properties. It currently reads:
1. Reflexivity: a≤b,
And I'm pretty sure it should be 1. Reflexivity: a≤a,
instead (i.e., every element is ≤ to itself). 1. cross join
2. natural join
3. equi join
4. theta join
5. inner join
6. left outer join
7. right outer join
8. full outer join
9. left semi join
10. right semi join
11. left anti semi join
12. right anti semi join
13. ???At best, such a comment is referencing something topical which most readers will get (and ostensibly be entertained by); at worst, it's a distracting non sequitur. It generally ties back to a community preference that comments are curiosity-satisfying before entertaining.
If it was an intentional allusion, then it may actually add depth/meaning to the conversation but we may not know since it was already downvoted…