Tree structure query with PostgreSQL
truongtx.me
truongtx.me
The advanced features allow you to have more than one way to do things, sometimes in a slightly more concise way (I've been tempting to use jsonb type in place of simple many-to-many tables if one of the values are just always be string). It's not that I'm expecting my app to be web scale or anything, but I'd rather not having to redesign everything one a query choke on a million records. And most of the docs tend to be light on performance characteristics.
As performance is one of the most important aspect in database system in general (which I'd say on par with consistency, and way a head of features), it'd be nice to have docs focus more on not just how to use features, but when it shouldn't be used.
In my experience, 9/10 production use cases are covered using a path as primary key with prefix matching (select path,data from tree where path='a/b' or path like 'a/b/%') - as a side effect your subtree nodes will often be on the same table page (mySQL by default, pgSQL when using CLUSTER).
Having said so, Postgresql has actually surprised me very little throughout time. The planner's "reasoning" is quite comprehensible. Inevitably I trigger a slow plan here and there but, once identified, correction is usually straightforward. My overall opinion is that postgresql has quite solid theoretical foundations and it shows.
What I mean is that, in advanced stuff, there'll always be some "magic", and that postgresql has the least amount of black box magic I've ever seen on a RDBMS (I'm looking at you, Oracle).
(Postgresql has been my non-clustered database of choice since about 2004. I'm definitely biased.)
I recently wrote a blog article about this, where I use recursive common table expressions solve the "eight queens" problem in SQL (using both Postgres and SQLite):
http://www.andreas-dewes.de/en/2015/queens-of-the-data-age-a...
Via a comment from what seems to be from Vadim Tropashko, here: https://communities.bmc.com/docs/DOC-9902
The book itself seems to be found here (where "trees in sql" is found in chapter 5): http://rampant-books.com/book_0601_sql_coding_styles.htm
I have no connection to Vadim Tropashko, just interested in knowing more about "Nested Intervals Tree Encoding".
[1] http://cramer.io/2010/05/30/scaling-threaded-comments-on-dja...
[2] http://cramer.io/2012/04/08/using-arrays-as-materialized-pat...
http://illuminatedcomputing.com/posts/2014/09/postgres-cte-f...
It's trickier than you might expect!
I have seen a few posts on HN regarding recursive CTEs recently and I shy away from them because it seems like an additional invocation for each different recursive lookup and a lot of the queries can be rewritten and potentially optimized using more traditional approaches.
"Yes, you heard that right, the SQL statement is 5x more performant at the database level alone."
I will have to do more testing and see what I can accomplish.
- Send one request for each level of hierarchy? Worst of all.
- Stored procedure? I don't think it would be optimised compared to a recursive query.
See also: http://stackoverflow.com/questions/5861272/postgresql-with-r...
http://stackoverflow.com/questions/935098/database-structure...
Where I have control of the design though, I still prefer to create structures that don't* require recursive queries*, even considering this means a little extra logic on insert/update/delete. Depending on circumstance (and for these examples assuming a tree or forest, not a more general graph) this structural difference is either storing the full ID path of each node or a matrix of "node Z is under node Y by one level, node Z is under node X by two levels, node Y is under node X by one level, ...), instead of (or as well as) the naive tree structure. Well written operations on these structures perform better than a recursive query, sometimes significantly so, but of course it is a trade-off as you have to accept the extra space (and potentially RAM) needed and extra processing on node changes, additions, deletes, & moves.
On a different product now (using PG) and guess what has come up? We need tree nodes! My first thought: anything but CTEs. ltree, materialized paths, neo4j, anything but CTEs. They've just burned me so badly before I'm too afraid to try them in PG.
Perhaps there are situations where recursive queries really are the only solution. I'd love to hear some examples.
[1] http://technobytz.com/closure_table_store_hierarchical_data....
With an MPTT structure you can query the entire tree (or subsets of said tree) with a single non-recursive SQL query, at the expense of having to use multiple statements to perform inserts and/or deletions. If you're really concerned about insert performance (which can be an issue for large trees), there are always hybrid approaches where you use adjacency lists for maintaining newly inserted nodes and then run an out-of-band operation to rewrite the relevant MPTT tree values.
*note: MPTTs used to be all the rage maybe 6-8 years ago, and it's like everyone forgot about them. What's up with that?
Of course you can slice and dice the ltree string up, but at what point do you just use a CTE?
Other query languages that make recursion much more bearable are SPARQL (on RDF data), Cypher (Neo4j) or Datalog (Datomic, Cascalog, etc). Would love to see more of those query languages being used.
It makes me cringe anytime I see a statement with complicated nested self joins to solve a problem that should not exist because most current database systems implemented the relevant standards years ago.
Start at page 48.
http://www.slideshare.net/billkarwin/sql-antipatterns-strike...