The Splitgraph Data Delivery Network – query over 40k public datasets
splitgraph.com
splitgraph.com
I appreciate the effort to make it easier for users to access heterogeneous data sets, but I really hope data vendors keep shipping raw CSV files. I don't want a company to gate access to the data, merely offering a proxy. I want to be able to download the whole raw datasets from the vendor directly if I want to.
In cases where that's not enough, you could roll your own types by putting the values in plain strings and it would still be strictly more expressive than CSV
Probably the closest thing I'm aware of is handing around a sqlite file, but I'm a little uneasy using a format that's meant to be a database as a transfer format. Dolt looks promising here too. Are there other ways?
Behind the scenes, we store them as cstore_fdw [2] files which is a columnar storage format that helps with analytical queries.
[0] https://github.com/splitgraph/splitgraph/
Note, we use mostly Python, some R, and a various range of ML or Optimisation tools, depending on the project.
We had to pick a single file format recommendation for sending 100GB+ tables on FTP servers or dropbox, scanning terabytes of useless stuff only to grap an key-value pair, and properly reading integer and UTF-8 columns. Turns out, Parquet is practical. Enough for users to start using it instead of CSV. It could be Avro, but it's just not as easy.
I actually think Parquet is pretty great in practice, I just have some issues with the sheer volume of abstractions necessary to implement it. I just wish it was anything other than Thrift.
I would probably choose Parquet over anything else, though.
https://medium.com/ssense-tech/csv-vs-parquet-vs-avro-choosi...
It's well-supported in Pandas and Kafka, has good schema support, and reasonably small compressed file sizes.
This idea makes such sense it's a little surprising nobody did it before.
That said, a simple compressed .sql file of INSERT statements can often go a long way.
The only reason CSV is widely used is because normal people think of data as spreadsheets, and asking them to fire up a database and shred JSON data into it is ridiculous when they just want to whip up a line graph or answer a simple question (e.g. "What was value X on a this particular date?").
For what it's worth, we run PostgREST [0] on top of the DDN, so you can get your query results in JSON and CSV files. For example:
$ curl -sSH "Content-Type: text/csv" https://data.splitgraph.com/cityofchicago/covid19-daily-cases-deaths-and-hospitalizations-naz8-j4nc/latest/-/rest/covid19_daily_cases_deaths_and_hospitalizations | wc -l
172
It's limited to 10k rows but we might have an ability in the future to "order" a CSV dump asynchronously and place in a destination (like an S3 bucket) of choice. $ curl -sH "Accept: text/csv" https://data.splitgraph.com/cityofchicago/covid19-daily-cases-deaths-and-hospitalizations-naz8-j4nc/latest/-/rest/covid19_daily_cases_deaths_and_hospitalizations?select=lab_report_date,cases_total,deaths_total | head -n5
lab_report_date,cases_total,deaths_total
2020-03-01,0,0
2020-03-02,0,0
2020-03-03,0,0
2020-03-04,0,0For the REST API endpoints (e.g. [0] [1]), we do set the Access-Control-Allow-Origin header to *, but for GET requests we do not send it at all. I'm not sure if this is the same as setting it to star. We can set it explicitly though; we do want to enable this use case (eventually we'll have quotas).
Soon we're releasing a Web UI for writing SQL queries. Part of that will include an HTTP (or websocket maybe) endpoint that takes a SQL query and returns the rows, so you'll be able to execute SQL queries directly from the browser.
As an aside, we'd love to get this working with Observable! Let us know anything we can do to help. You can email me at miles@splitgraph.com or join the Discord and we can figure it out :)
[0] Docs: https://www.splitgraph.com/cambridgema-gov/covid19-cumulativ...
[1] Endpoint (powered by PostgREST): https://data.splitgraph.com:443/cambridgema-gov/covid19-cumu...
If you're testing with the same endpoints, you may need to give the cache a few minutes to evict the old values missing the header.
There's no comprehensive single specification. The closest is an RFC which completely misses major pieces (eg handling of binary data, and more).
Using SQLite as the interchange format is better. :)
40,000 data sets - even if many are just diff versions - is a ridiculous number to manage or even know about on a non full time basis.
Data driven decisions need data yes, but they also need people to know the data exists. And what it means.
And this is just external curated data - use this as the standard for what each department should be producting internally.
In fact that's a good idea - a data publishing standard - not just the data types / schema, but actually supplying it through a format that is consumable by others.
Something is not entirely clear to me right now: An image is an immutable snapshot of a dataset at a given point-in-time - great - but, can I query the same dataset at two different PIT using layered querying in SQL ? Something like this: SELECT * FROM dataset:version-1, dataset:version-2
Also, are you storing the entire dataset as new or only the diff between versions (and later reconstruct the full image) ?
Now, onto the things that could be improved...
- Git-like semantics (pull, push, checkout, commit) are poorly suited for versioned, immutable datasets. Just (intelligently) abstract fetching and sending datasets by looking at the SQL query (dataset:version-2, above)
- Versions should be at least partially ordered and monotonically increasing. Hashes doesn't convey the information necessary to decide if dataset:de4d is an earlier version of dataset:123a, or not.
- Tracing a derived dataset provenance will only work if you can assert that the "code" or transformations applied to the original dataset is deterministic (side-effect free). So, either you have your own ETL language that you can execute in a sandbox and add a myriad of useless stuff for creating and scheduling pipelines (please don't do that!), or you just let it go and don't end up becoming Pachyderm (sounds great!).
Think more about Kafka's topic/message objects, with each message being an entire table, and their Stream API
> can I query the same dataset at two different PIT using layered querying in SQL
Yes. We have a query that does this on our home page (it's the second in the carousel at the top):
SELECT
new.domain AS domain,
new.id AS id,
new.name AS name
FROM
"splitgraph/socrata:20200809".datasets old
RIGHT OUTER JOIN
"splitgraph/socrata:20200810".datasets new
This is querying two versions of the same image.> are you storing the entire dataset as new or only the diff between versions
Basically we store the diffs between versions, yes. The simplified explanation is that data images are an initial snapshot + chain of diffs ("delta-compressed"). You can read more in the concepts section of the docs. [0]
> Git-like semantics (pull, push, checkout, commit) are poorly suited for versioned, immutable datasets
We pretty much agree with this. Some similar projects take the wrong approach and try to implement 100% of git commands "for data." But it's a square peg trying to fit into a round hole. The use cases are not the same. There are some similarities, but they're limited. Our goal was to step back and think from first principles: What do we like about our coding tools? How can we get the same benefits with data?
> Versions should be at least partially ordered and monotonically increasing. Hashes doesn't convey the information necessary to decide if dataset:de4d is an earlier version of dataset:123a, or not.
Sure. If you want monotonically increasing versions, you can do that by tagging an image with `sgr tag`. (FWIW, image hashes are currently random, but the hashes of objects that comprise them are not -- they're actually content addressable representations of the changeset from the root to that version using an algorithm called LTHash.)
> Tracing a derived dataset provenance will only work if you can assert that the "code" or transformations applied to the original dataset is deterministic (side-effect free).
Yes, definitely. Dataset provenance works best when you use Splitfiles [1] to construct images. It's still possible to run into problems with non-determinism, but for the OLAP use case, we think those situations should be rare.
Anyway, I'm curious to see where your project will end up. You put much more efforts in the design than most "for data" tools !
Cheers !
I am not affiliated at all with Pachyderm, I am just curious about this problem-space.
I'm trying to understand the architecture of Splitgraph. Are all foreign data wrappers controlled directly by you, or can third parties host a database and connect it to Splitgraph in a federation?
You can also run a Splitgraph engine locally and add your own FDWs to it. We have a lot of scaffolding around FDWs to make their instantiation much more simple and even wrote a blog post [0] about adding a custom FDW to Splitgraph.
However, in the future we'll be adding the ability to add your own backend data sources to Splitgraph that it can proxy to (whether as a private dataset on the public Splitgraph instance or as a "data virtualization" layer when you have an in-house Splitgraph deployment).
The cool thing about this is that this can be a single gateway to all your data silos (Snowflake, third-party SaaS, public datasets) that can handle federated query execution, data discovery and access control (e.g. firewalling queries to sensitive columns even if the backend data source doesn't support this level of granularity).
That’s actually pretty cool, to see a public URL with PostgreSQL protocol signifier like that.
Makes me wonder if any developers or DB Architects ever thought of putting their resume in a DB and putting a public read-only postgresql:// URL on their business card :D
If you build the client, and a web page/app and also document how you did it and also show us the code, that'd be much more useful.
Saw this more before I started refusing interviews with the HugeCos, but the strangest flavor of this I've run in to was at an early startup - I suspect dude was acting out an arrogant genius script, hoping to convince people he was one. (It came out as very weird, not in a good way.)
- usually the first person to screen or introduce you won't be a developer or perhaps not even technical, so you've put yourself out of the running early on. I can query it, but many who might be in a position to put you forward might not. If you want to do that though then fair enough, that's your choice.
- reflecting on my current situation where I'm busier than normal right now and I want an easy run on non-development tasks ;)
So I PUT in my resume to the actual IP address, got an interview. Alas they were a strict Windows shop, and at the time I was a Unix Perl dev
So a website resume, like literally every other candidate...
I think you've missed the entire point of the idea... which is to stand out with a different approach
Sure websites are normal, but if you present me with the source and you wrote it (i.e. it's not just a wordpress site) and it's something worth looking at then I can already see that you can do something interesting and of value.
On a related note, I've long wanted longer identifier lengths in Postgres so we can have more meaningful column names but the powers-that-be have always refused... hopefully one day it'll increase in the default distribution.
> identifier length 63 bytes can be increased by recompiling PostgreSQL
Maybe they compiled their postgres with a different limit? Just a guess I, haven't tried it.
“ ...
The system uses no more than NAMEDATALEN-1 bytes of an identifier; longer names can be written in commands, but they will be truncated. By default, NAMEDATALEN is 64 so the maximum identifier length is 63 bytes. If this limit is problematic, it can be raised by changing the NAMEDATALEN constant in src/include/pg_config_manual.h.
...”
https://www.postgresql.org/docs/current/sql-syntax-lexical.h...
We also use this to drop unwanted queries and rewrite clients' introspection queries (e.g. information_schema.tables) to give them a list of featured datasets instead of normal Postgres schema names.
The best link/example I found was https://github.com/beargiles/passwd-fdw and it's quite easy to follow the code and understand all the moving parts.
Once you've written a FDW you'll see them everywhere.
In fact the same author wrote https://github.com/beargiles/zip file-fdw and https://github.com/beargiles/tarfile-fdw
If you (still?) need inspiration and want to see what already exists: https://wiki.postgresql.org/wiki/Foreign_data_wrappers
Simpler, using a 'generic' file-based FDW shipping with pg's sources: https://aaronparecki.com/2015/02/19/8/monitoring-cpu-memory-...
There's a python wrapper to get your feet wet (or prototype an idea) : https://github.com/Segfault-Inc/Multicorn (though I'm not sure how maintained this is).
The only annoying part is that you're plugging your code to an interface that might (and has sometimes) broken between releases of PG. So kind of the same fun as maintaining a gcc plugin...
By the way, anyone has any idea on the licensing terms/issues of PG FDWs and PG extensions in general?
There’s also this great post about using FDWs for parallel query execution, by David Grier at Swarm64. [1] They seem to be doing cool things with FDWs too.
Personally I think proxies are a really powerful abstraction in general. Cloudflare and Twilio are two examples of companies built around proxies.
[0] https://www.splitgraph.com/blog/foreign-data-wrappers
[1] https://swarm64.com/post/scaling-elastic-postgres-cluster/
I'm not sure where you're going with this product, but I like the idea of proxies and your idea of a DDN, and I wish you the best.
I'm trying to 'bind them all' at my job right now and Postgres is very inspiring with its extension success stories, and all the FDW work happening. And once you can bind to C, you can mostly chose your language :-)
In general, some clients will have issues with introspection queries (which they use to show the list of available schemas). And even when introspection works, we can't show you all 40k datasets or it might break your client. So we just show "featured" datasets, and for a more exhaustive list you can go to the website to find a dataset.
But, you can still query any dataset on Splitgraph regardless of what shows in your client's schema list. You can go to https://www.splitgraph.com/explore to find datasets, and from each dataset's repo page, you can click "tables" or "query SQL" to get a sample SQL query to run.
Congrats on the product BTW. Very promising!
I've been looking forward to something like this for years.
Could you try again when you have the chance?
But for nested data (XML, JSON, etc.) it really isn't the best language for that. I am talking here specifically about not querying data that is nested, but actually getting query results in a nested format. SQL can do it (almost all major databases have XML and JSON support) but it rally isn't the easiest thing to use.
We should also consider the capabilities of PostgreSQL to query JSON documents.
I can't find pricing.
We're actually looking for early customers to beta test the private deployment, more on that here: https://www.splitgraph.com/about/company/private-cloud-beta
p.s. Glad you like our privacy policy at least. :) We hate third party trackers.
we have it running on our own (cheap) server, but we fear we may get overwhelmed by too much traffic if the project becomes very successful. Would this be a solution for us? Is it for free?
In terms of price, we'll eventually add quotas (storage + server side query execution) on the public tier. But the main monetization will be private deployments. In an ideal world, the private deployments will be able to subsidize the costs of some of the open data on the platform. Certainly we'd like to be able to support projects like this one.
[0] https://github.com/splitgraph/splitgraph/tree/master/example...
We want to initially focus on the use case with lots of diverse backend datasets and ad-hoc APIs (maybe with a no-code like solution on top of a generic FDW) where performance won't be the bottleneck. If necessary, the backend data sources can perform aggregation and fast query execution. For example, you can also put Splitgraph in front of Presto (through JDBC). The value we want to provide in these cases is:
* granular access control (e.g. masking for PII columns, auditing etc)
* firewalling/query rewriting/rate limiting (for publicly accessible endpoints that proxy to internal databases that vendors want to publish more easily than through cronjobs with data dumps)
* cataloguing (so you get to discover datasets/data silos, get their metadata and query it over multiple interfaces in the same product)
We also like keeping the PG wire format in any case, as there are so many BI tools and clients that use it that it makes sense to not break that abstraction. We started with PG FDWs just because of the simplicity and the availability of FDWs, but we might swap the actual Postgres FDW layer for some faster execution in the future, if it's needed.
Behind the scenes, for Splitgraph images, we use cstore_fdw as an intermediate storage format (it's a columnar store similar to ORC with support for all PG types like PostGIS geodata). There's a potential in using this as a format for a local query/table cache on Splitgraph nodes that we intend to deploy around the world for low-latency read-only query execution.
We want to support both these use cases. For (a), Oracle would be an "upstream" to Splitgraph. We'll need to write a plugin that implements the FDW and does introspection. Eventually, we want you to be able to configure upstreams from the Web UI.
For (b), you can probably find a way to query Splitgraph from Oracle, e.g. using Oracle's "gateway" feature [0]. What's nice about Splitgraph is that it's compatible with any SQL client that can speak the Postgres protocol (or ODBC). So if Oracle can connect to a Postgres database, it can connect to Splitgraph.
We have instructions for how to query Splitgraph from within ClickHouse at [1]. We're actually giving a presentation about this to a ClickHouse meetup on Sep 10, feel free to join. [2]
[0] https://docs.oracle.com/cd/E18283_01/owb.112/e10582/gateways...
[1] https://www.splitgraph.com/connect
[2] https://www.meetup.com/San-Francisco-Bay-Area-ClickHouse-Mee...