Though to be serious: what do you expect a graph database to provide that sqlite cannot / does not do efficiently?
Though to be serious: what do you expect a graph database to provide that sqlite cannot / does not do efficiently?
(Note: I've actually written a graph database from scratch, for exactly these reasons.)
Also, in this case, "probably less" is "multiple orders of magnitude slower".
const unsigned *edge_indexes = (const unsigned *) mmaped_structure_on_disk[disk_offsets[index]];
That's not the same as just being able to access those via an API; locality in this case means that you shouldn't need extra seeks for every single value, nor have to make a bunch of round trips through SQL.That is the primary difference between traditional relational databases and column-oriented databases. Normal relational databases have row-based locality; column-oriented databases have column-based locality.
So the question is, do we actually want to run graph algorithms or is the data graph structured for other reasons? You're implying that choosing a graph representation means we want to perform graph analyses. I disagree with that if we're still talking about the semantic web.
RDF is a general purpose knowledge representation model. The triple structure lends itself well to combining data from different sources with little coordination. It happens to form a graph, but running graph algorithms is just one of many special purpose problems.
I'm primarily replying to:
> What is a graph database? A miserable little pile of joins.
> Though to be serious: what do you expect a graph database to provide that sqlite cannot / does not do efficiently?
That seemed like a general questions of, "What are graph databases for, and why would someone use them?" And I'm trying to answer that question.
If there was some kind of "normal" query on thousands-to-millions of items that was prohibitively terrible on SQLite but not on graph-database-X, yea - I'm interested :) And I totally buy that graph DBs are better at graph queries in general. I just have yet to hit these kinds of limits in my use of SQLite (a fair number of instances with tens of gigabytes, a few with billions of rows) - a sprinkling of reasonable database design addresses almost all issues.
The main one I can see is that, with longer-term use, SQLite's lack of any way to force locality would be fairly crippling. You'd need to make a reasonable sort order and periodically re-insert data in that order to optimize / vacuum. That's... technically achievable, but is a big downside compared to something that can dynamically organize / optimize it based on [some heuristic].
Fixed that for you. ;-)
Actually a few RDMBSes (Oracle, Postgres, MS SQL) have graph extensions. I've never used any of them, but I assume they work around some of the basic unsuitability of traditional tables for storing graphs.
Triple stores are essentially relational databases in 6th normal form. But relational databases like SQLite don't have good join algorithms to deal with this (they do pairwise joins instead of the worst case optimal ones like Leapfrog-Triejoin or Tetris). They also lack good interfaces for so many joins, you want something more declarative like Datalog/SparQL/GraphQL, than to explicitly write out every join.
That has been my pet peeve for a while, and can make it hard to define navigation.
Totally not a deal-breaker though. I'd still use sqlite because I ### love it :)
relation_id │ relatee_id
────────────┼───────────
1 │ x
1 │ y
voila, directionless relationships. you can even do N-way, just insert more rows with the same relation-id.> or normalize to yet another join table
This is also semantically incorrect. There needs to be exactly 2 rows there. You cannot in a declarative way, prevent that if you use this approach.
It's also a known dilemma, so we don't have to rediscover the wheel here.
Granted, it might not be very nice to query.
What you described is, IIRC, also what some file-based graph DBs do in the background with sqlite and abstract away from you (I've seen a couple custom ones in some projects). Left with a RDBMS, you just need to do it yourself and analyze how much it costs.
Also I have no idea why a separate table is a negative / constraint of some kind. It's a natural way to model it.
When you are following a chain of relations (a vector), you end up losing a lot of performance.
> not entirely sure what you mean by declarative
Guaranteed by the database semantics, not imperative code even when it runs on the DB.
I don't want to come off sounding like I think it's a bad idea to map graphs on RDBMSs, it's just inconvenient sometimes. Usually not enough to complicate your setup, adding another database, but rarely it is.
I'm not sure though about the suggested use case here, I really don't know it enough to make a suggestion. In such cases I always pick sqlite or postgres (depending on the client model) though. You can't be too wrong with those, and you are most of the times right :)
Not to mention the crazy extensibility of pg and the stuff you can do with it.
If you meant to prevent "all inserts are now [run this stored procedure / multi-statement operation / transaction with N steps]", then yeah - I agree that runs counter to "normal" use in most cases. It's certainly dramatically more error prone. Triggers don't need this though.
re chain of relations: I haven't poked too hard in this direction in SQLite, but I do totally believe its query planner isn't too sophisticated. And though you can get pretty good data locality with fancy design around the DB, you certainly won't get good locality just by inserting a bunch of data and running queries.
A simple example would be to link 3 brothers with the same relation: the worse solution would be dividing it in 3 different binary relations; the reality is that each brother is part of the “brother relation” set by way of sharing parents.
Semantic web I assume is full of such directional relations. Bidirecitonal relations are the exception. Things like "causes", "indicates", "enables", "prevents", ...