Time-travel queries in CockroachDB
cockroachlabs.com
cockroachlabs.com
`SELECT (, $querytime) FROM table1 WHERE ...;`
Then based on some code in my application run a second query:
`SELECT FROM table2 WHERE ... AT $querytime;`
So much frontend code makes assumptions that databases aren't modified between consecutive queries (like graphql-js). With an API like this it would be trivial to make those queries correct. (And we wouldn't need to abort, and we can cross database instance boundaries in interesting ways). The timestamp is also super useful for doing isomorphic rendering of live-bound data - the server can send the timestamp of the data queries it used to render the page. When the client JS loads it can reconnect to the server and pass the rendered timestamp back to check for deltas between the rendered version and the current database view. This in turn lets you to safely cache server renders, as well as a bunch of other fun things.
Hats off to the CockroachDB team! Fingers crossed some of these features start making their way into other databases I love. (Looking at you, Rethinkdb!)
This has been in Oracle for a few years now https://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns...
You would need to be hiding under a rock, like a cockroach I suppose, not to know that Oracle and SQL Server 2016 have this :-)
In a way it's similar to some folks going crazy because you can do this or that in the browser when desktop OSes have been able to do it for ages... generational shifts.
Inside the transaction you will see only changes made within the transaction.
I think the stateless nature of time-travelling queries would map much better to the stateless nature of HTTP requests.
For writing, you compute a change-set against a particular snapshot (making explicit the fact that you're always updating based on assumptions from possibly-stale data) and then submit that changeset to a write-linearizing "transactor" server-process that outputs new snapshots. The transactor is programmable, so it can do whatever interesting things you like to coalesce updates based on their submission order and the snapshot they were calculated against (CRDTs, last-write-wins using the snapshot-ordering, etc.)
I assume the indexes are laid out like (col, timestamp)? Can you handle an access pattern where keys are continuously inserted with the same value, and then deleted shortly after? Will queries for the value work efficiently, or have to scan all rows inserted with that value for the last 24 hours? Is there a way to tweak GC to run more aggressively on a particular table (knowing that you wouldn't be able to query back in time)?
We have an access pattern like that in our database. Rows are inserted into the table with x=null, then later x is set to some unique value, but we need to query where x is null in order to set the actual value. At one point we had a long running transaction that prevented the database from cleaning up old records, so the query for X is null grew slower and slower to the point where it almost browned us out.
Basically, yes, all keys the KV, including the index entries, include a timestamp suffix.
Repeated edits to the same value will accumulate MVCC revisions until they are GCed, and those will be iterated over during access, so, as you point out, a use-case like yours would likely benefit from shorter a GC cutoff and GC _is_ configurable in cockroach.
However, we are able to support schema changes
between the present and the “as of” time.
For example, if a column is deleted in the present
but exists at some time in the past,
a time-travel query requesting data
from before the column was deleted
will successfully return it.
I've noticed that hardly anyone writes about DDL for temporal tables. Snodgrass's book doesn't cover it. What happens when you add a `NOT NULL` column or change a column to `NOT NULL`? That kind of thing. There is plenty of research on temporal tables, but I haven't found any attempt at defining rules for these changes. (If someone knows of a paper or book chapter, I'd love to hear about it!)https://www.postgresql.org/docs/6.3/static/c0503.htm
It's actually very easy to implement if you use the "append" version of MVCC (which Postgres does). All you need to do is just disable garbage collection (e.g., the vacuum).
Reminds me of Microsoft SQL Server removing support for natural language data queries, only to add it back years later.
It would be interesting to see a list of features from major database management systems that have been removed over the years.
The only other thing I can think of right now are in-memory optimized indexes (e.g., T-Trees) from the 1980s. These were later removed and replaced with B+trees (or skip lists if you're MemSQL) because CPU caches (SRAM) got much faster than memory (DRAM).
I have used it in production for years and it works great, but does indeed use a lot of disk space if you enable it for all tables and have many updates.
It's not a full implementation (it lacks the new syntax like `AS OF SYSTEM TIME`) but you can work around that with `UNION` queries and the containment (`@>`) operator.
every table had meta columns defining bounds for validity for this version of a given row. an update copied the row, applied changes, updated validity timestamps on the old and new copies.
aside from the disk space problem you mention, the other issue was that every update required a write to every index on the table, even if the indexed column hadn't been changed. makes simple updates much heavier than one might naively think...
I originally wrote that I wasn't aware of any other DB that had this. I should have specified any other SQL DB, since I was aware of Datomic.
While working on this feature I searched on Google for the syntax specified ("AS OF SYSTEM TIME"), but didn't find it referenced except about a third-party Postgres extension. It is unfortunate that Oracle and MSSQL didn't come up in my searching, since they support this feature.
I've edited the blog post to be more accurate in listing some of the previous work.
Similar support can be found in quite a few places. It is in the SQL:2011 standard: https://en.wikipedia.org/wiki/SQL:2011
I always hated with passion keeping timestamps and messing the database design so I can have some sort of time awareness, I always thought that this is supposed to be handled by the database itself, I'm just a user.
I know there's Datomic[1] but its stack is way different than what people are used to (around here) and I'm yet to find an application that would justify using it (yeah, I'm not proud of that).
If anyone from Cockroach happens to read this, I have some questions:
* Are you guys the first database vendor to provide this as first class feature?
* How is the time travel performance-wise? What if I have a product that rely on this heavily?
* How the database would handle some deleted columns on the schema reappearing after some time? It would consider the same as before? What if the type is different?
Kudos for the feature, I barely know CockroachDB but now I have a good reason to try it.
No, we are not the first SQL vendor to provide this. And many other non-SQL databases also have this feature.
Performance is faster than other reads, in general, because of less risk of transaction retries.
Columns can come and go, and change types, and that is all handled correctly. If a column reappears as a different type, it will work correctly. This is because we also version the table schemas each time they change, so we can always fetch the correct schema when doing a time-travel query.
So while cool, it seems like CockroachDB's marketing/content team is what is winning here. I don't know how they do it, but it is impressive.
see: https://docs.snowflake.net/manuals/user-guide/data-time-trav...
disclaimer - I work there.
(Although I admit that I haven't tested this assumption, since Snowflake appears to be proprietary.)
Example: I got paid yesterday and the operation will be recorded only tomorrow.
The first kind of query AS OF today will never show the payment. The second one will do (assuming that behavior is appropriate for the application, better examples are possible.)
CockroachDB, SQLServer and Oracle implemented the first one. That's why they are writing about backups.
Edit: see this PostgreSQL extension for the second kind of queries http://pgxn.org/dist/temporal_tables/
> Currently, Temporal Tables Extension supports the system-period temporal tables only.
Also here is the same extension on github: https://github.com/arkhipov/temporal_tables
How high you can set it depends on your access patterns -- there is some overhead to iterating though MVCC revisions during reads, in addition to the on-disk space you mention.
If your workload involves frequent writes to the same rows, GCing some of those revisions sooner would have a greater impact, whereas if you have a write-light workload, or if your writes are spread over rows such that a given row doesn't doesn't see frequent repeated updates, then you could probably use much a higher GC threshold with minimal overhead.
The only other DB I know of which has this is Oracle, where it's called "Flashback". Are there any others?
http://www.cs.cornell.edu/projects/quicksilver/public_pdfs/f...
They want to power the backend of hundreds of millions of energy sensors for a smart power grid.
Away from applications that really need to solve the byzantine general problem, I see no reason to use the blockchain.
In fact, I wonder if there are fintech start ups using language like blockchain in their pitch docs, but in actually plan to use versioning databases like this feature here of CockroachDB or Datomic.