Show HN: Query SQLite files stored in S3
github.com
github.com
it was a non-trivial overhead to have to send an http request per column, when i could have sent one with multiple ranges.
i can imagine something similar with this, fetching multiple pages in one request
Can you expand more on this? I keep hearing that on HN but what guarantees does FDB provide over other key/value DB’s?
https://apple.github.io/foundationdb/cap-theorem.html
And
https://apple.github.io/foundationdb/consistency.html
For a summary. Tldr is that FDB provides transactional guarantees similar to an rdbms but can be distributed and has optimistic concurrency, meaning locks are not necessary.
In the context of SQLite that’s the main issue it has and FDB is positioned to solve it.
[1] https://pkg.go.dev/go.gazette.dev/core@v0.89.0/consumer/stor...
Cool way to store data with indexes into it in a way that makes it as easy to use as copying around and opening a file; no need for dumps or restores or server processes.
There's still an argument for columnar formats like arrow, but compatibility is iffy compared to SQLite which "just works"
I am also now starting to look at SQLite as a sort of application framework / operating system. The SQLite VM is running on billions of devices right now without any issues. Seems like a safe bet if I wanted to use the relational/SQL model to represent most of my application state & logic. Anything else I want to bring to the party I can inject by way of application-defined functions.
[1]: https://github.com/papers-we-love/papers-we-love/blob/master...
SQL is so much more powerful than most developers are aware. It's not just some annoyance to trod through in order to get to your data. It is an entire data-as-computation paradigm that also happens to be a domain specific language.
SQL is functional. It is also relational. Figuring out how to combine both of these properties across your entire domain is peak elegance. We got pretty damn close on our current iteration. The walls of the matrix are a bit messy, but from inside a given SQL expression you can't tell. It all looks very clean from the inside.
SQLite represents the most stable and portable foundation upon which to construct one of these systems. Nothing else comes close.
Even if JSON blobs happen to be the most convenient way to represent your data, you can still just put those blobs in an SQLite database and maybe worry about converting them into something relational later.
S3File (from s3fs) inherits from AbstractBufferedFile[0], which has a cache[1], implemented here[2]. I haven't read through all the code yet, but experimenting with different cache implementations will probably make the VFS faster. It will also depend on the type of queries you're executing.
[0]: https://github.com/fsspec/s3fs/blob/ad2c9b8826c75939608f5561...
[1]: https://github.com/fsspec/filesystem_spec/blob/2633445fc5479...
[2]: https://github.com/fsspec/filesystem_spec/blob/2633445fc5479...
It'd be very handy if this was packaged as a CLI that worked like `sqlite3`, so you could get a SQL repl by running:
s3sqlite mybucket/mydb.sqlite3I think SQLite is fantastic, but this just smacks of scope creep.
To elaborate on a specific case, think about a 'package-lock.json' file in a Node project. These files are frequently many megabytes in size, even for simple projects, and if you wanted to do something like inventory _every package_ used on GitHub, it would be a ton of data.
You might argue that you could compress these files because they're text, and that's true, but what about when you only need to read a subset of the data? For example, what if you needed to say, "Does this project depend on React?"
If you have it as JSON or Protobuf, you have to deserialize the entire data structure before you can query it (or write some nasty regex). With SQLite you have a format you can efficiently search through.
There are some other formats in this space like ORC and Parquet but they're just optimized for column-reads (read only _this_ column). They don't provide efficient querying over large datasets like SQLite can.
This is at least my understanding. If anybody has a perspective that's opposite, I'd appreciate hearing it!
More importantly that OSM is considering providing MBTiles directly (besides PBF)[2].
(Full disclosure: I wrote most of both of these)
S3 is delivered over a stateless protocol (http) and AWS makes no promises about any given request being fulfilled (the user is merely invited to retry). The safety of your data is then further dependent on what storage tier you chose.
There just seem to be so many footgun opportunities here. Why not just use the right tool for the job ? (i.e. hosted DB or compute).
Because sometimes you want a database for 10000 rows, or you have 5 logins a month and you don't want a $30/month database running in the cloud.
There's a market out there for real "server-less" database that charges you per rows stored, is priced per read/write operations, and is reasonably priced for a 10000 rows per month, without having to calculate how many 4KB blocks you are going to read or write.
Using dynamoDb, you're going to have a hard time querying if field A, B, and D are included. If you add a fifth field, it's going to be a pain to add to historical data.
If I have to start writing joins by hand, what's the point of even having a database?
I don't think it's like that. AWS already offers services like S3 Select[0] or Athena[1] that do something similar.
> the user is merely invited to retry
Another reason why I used s3fs instead of manually making requests.
> Why not just use the right tool for the job?
I certainly have multiple uses-cases where creating an SQLite database locally and distributing it via S3 (for read-only usage) is orders of magnitude more convenient than the alternatives. It's hard to beat the developer experience of a local SQLite database.
[0]: https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectOb...
I haven't tried this myself but parquet + S3 select should be especially good for analytical queries.
It occurs to me that because a FILE * is an opaque pointer, it ought to be possible for a libc to provide this functionality: the FILE struct could contain function pointers to the the underlying implementations for writing, flushing, etc.
This ought to be backwards compatible with existing FILE * returning APIs (fopen, fdopen, popen), while allowing new backing stores without having to rewrite (or even recompile) existing code.
FWIW S3 kind of is that "de facto" interface. There were attempts at standardizing it via OpenStack's SWIFT project but to my eye S3 remains the industry de facto for better or worse.
However I like the idea of using a local store with litestream to S3 and updating to the latest db data from S3, if using my application on another device or computer. Sort of like github.
Tailscale was looking into this option, instead of Postgres and other DBs. https://tailscale.com/blog/database-for-2022/
Cheers
https://gist.github.com/Q726kbXuN/56a095d0828c69625fa44c2311...
It's not really useful for deep dives into data, though it has gotten me out of a few jams that would have otherwise required a real database just to pull out a value or two from a large dataset.
With this you don't need to do that - the software magically fetches just the pages needed to answer your specific query.
Having just a single file has some advantages, like making use of object versioning in the bucket[0]. I also think that relying on s3fs[1] makes the VFS more flexible[2] than calling `boto3` as `sqlite3-s3vfs` does.
[0]: https://s3fs.readthedocs.io/en/latest/index.html?highlight=v...
[1]: https://s3fs.readthedocs.io/en/latest/index.html
[2]: https://s3fs.readthedocs.io/en/latest/index.html#s3-compatib...
So there are for completely different use cases, thanks!