[HN Gopher] An unscientific benchmark of SQLite vs. the file sys... ___________________________________________________________________ An unscientific benchmark of SQLite vs. the file system (btrfs) Author : leeoniya Score : 75 points Date : 2022-02-12 17:09 UTC (5 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | CJefferson wrote: | I couldn't see any fsync (or similar) in your filesystem code | (sorry if I missed them) -- it doesn't seem like a completely | fair comparison, as sqlite has various promises about commits | being completely made, etc, which you won't get from just | chucking files on a filesystem. | bogota wrote: | If you only care about storing data and not doing any complex | operations or query against it why are you using something like | sqlite as well? | | It's not a comparison as being in sqlite makes the ability to | access this data significantly easier. This is comparing apples | and dogs and i don't see the merits. | baq wrote: | SQLite makes seeking in a file using a lookup table look like | a complex operation from the developer's perspective, which | is absolutely a good thing unless you have a strong | alternative rationale for your use case. | kevingadd wrote: | It's not uncommon to see people advocate for using sqlite as | an alternative to flat files or json blobs. In particular, | transactions provide nice properties vs a web of separate | flat files, and the stronger schema can be a good alternative | to json. There's a lot of great existing sqlite tooling, too. | samwillis wrote: | Not only other people, the creators also advocate for it as | a file format: | | https://www.sqlite.org/aff_short.html | | https://www.sqlite.org/appfileformat.html | electroly wrote: | In one application I use sqlite to store JPEG thumbnails. | That's it; there's nothing else in there. It's super handy; I | specifically needed to reduce the number of files that I open | and close because that's slow on Windows/NTFS. SQLite made | this trivial. I could have managed a binary pack format on my | own but I didn't have to. | asperous wrote: | Another alternative that I've seen used is a zip or tar | with no compression if you are just appending files and | reading but only rarely updating or deleting. | | But sqlite is still better, it is more reliable, a bad | write on that end of zip index destroys the whole zip | archive and sqlite also gives you a lot more potential | flexibility later on if you need to add metadata or | something else. It is better in terms of inserts and | deletes, although you will still need to vacuum. | hinkley wrote: | A bad write on a zip file destroys the O(1) seek time, | but it doesn't destroy the zip. That goes back to PKZip | trying to work on floppies and over modems. You can still | do an O(n) seek on a particular file, or expand and | recompress the file to recover whatever isn't truncated. | | For this situation it does matter, but it is recoverable. | asperous wrote: | Oh interesting! Good to know | jbluepolarbear wrote: | You could have easily done that with a single file with a | tail header for look ups. | electroly wrote: | I'm aware; I mentioned this at the end of my post. This | is still easier. I want to clearly express how absolutely | trivial it was to use SQLite for this. I didn't really | have to think about anything. | baq wrote: | Easier than SQLite? With less bugs and better tests? | | SQLite advertises itself as an fopen replacement. Sounds | like a perfect match for parent's use case. | jbluepolarbear wrote: | Yes easier, as in time to integrate and get working | correctly. I've used SQLite extensively over the last 10 | years and yes it's a good solution, but not a replacement | for fopen. A flat file would be easier to integrate, | test, and harden over SQLite. Would take about the same | time as integrating SQLite into a system for the same | purpose and would be easily extendable to support | features as the system grows. | KerrAvon wrote: | Depends on the indexing needs, right? Something like IFF | should be fine if you need a sequence of images to store | that you don't need to actually query for individually. | baq wrote: | Always, but I find it really hard to see how not using | SQLite in this use case is the better option. Maybe if | you need every single percentile of performance? In 99% | of other cases just go with SQLite. | AceJohnny2 wrote: | Indeed, "SQLite does not compete with client/server | databases. SQLite competes with fopen()." | | https://www.sqlite.org/whentouse.html | christophilus wrote: | Yeah. I mentioned that in the final test where I write to a | temporary file, then rename. This is much slower, probably due | to an implicit fsync. | electroly wrote: | You can disable the fsync calls in sqlite if you wanted to do | a little better with this benchmark. You're also explicitly | choosing the WAL in your go-sqlite3 configuration which is | not at all replicated by your filesystem test. I think, | honestly, that you're just going to mislead and confuse | people who don't know any better with this writeup. I can | write faster to /dev/null, too, but that isn't a very | interesting comparison. | HideousKojima wrote: | Does /dev/null support sharding? | pa7ch wrote: | Yes. | cafxx wrote: | I am not aware of implicit fsyncs. Can you please link to | what you are referring to? | kevingadd wrote: | If you're using the same file, it would make sense if the db | 'warms up' by growing enough to comfortably hold all your data. | christophilus wrote: | Good point. That's the more probable explanation, actually. I'd | imagine the execution plan would be cached within the first | batch of requests. I hadn't considered the file resizing, but | it's a good hunch. | corbani wrote: | Did you seee this? https://www.deconstructconf.com/2019/dan-luu- | files | rurban wrote: | How about a fast filesystem? This is by far the slowest. | christophilus wrote: | That's fair. It's the file system I have easy access to. I | should spin up a VPS and use ext4 or xfs. I may do that when I | have some spare time. It looks like I may get double the perf | by making that switch. SQLite also seems to get a bump on | different file systems. | | Edit: just ran it on EXT4 on Linode. | | SQLite: 8.7s | | EXT4: 18.3s | tmikaeld wrote: | I'd bet that xfs is the fastest, it usually is | nh2 wrote: | > then rename it to overwrite the existing file ... This makes me | think that probably my initial file tests weren't waiting for | fsync, but the rename forces the application to wait. I'm not | sure. | | I can answer this one. | | This is conflating atomicity (atomic rename) with durability | (fsync; whether data is guaranteed to be on disk and will survive | power failure). These are two orthogonal things. | | When you use sqlite with default settings, it will give you both | atomicity and durability. | | If you want to get both in a file system like btrfs, you need to | (1) fsync the written file, (2) do the atomic rename, (3) fsync | the directory that contains the renamed file. | | Some file systems, like ext4, do automatic fsyncs "every couple | seconds", but that is of course not something to rely on when | benchmarking. | pmarreck wrote: | Now you got me intrigued by the concept of a big flat raw sqlite | file AS a filesystem... I see there is an old FUSE implementation | christophilus wrote: | TL;DR: yes, probably for a real-world use case. | | Anyway, the perf is good enough for what I need, and the | flexibility of querying makes it well worth it. There is | something nice about plain text files, though. | christophilus wrote: | I'm the author. Out of curiosity, how did you find and post this | before I did? | leeoniya wrote: | i follow you on github :) | | sorry! | christophilus wrote: | Ha! No worries. | formerly_proven wrote: | For SQLite in this test writes in particular means transactions, | where each transaction contains exactly one write. | christophilus wrote: | Yeah. It's simulating the behavior of a CRUD server I'm | thinking about writing. I wouldn't be able to batch writes very | easily there, so it would be a transaction per write. | CalmStorm wrote: | The article doesn't mention whether SQLite WAL mode is on. That | could make SQLite significantly faster: | https://sqlite.org/wal.html | bungle wrote: | It mentions it at the end: | ./tmp.db?_timeout=5000&_journal=WAL&_sync=1 | | Not sure if it was updated after your comment. | ape4 wrote: | A quick google shows there are few FUSE SQLite implementations. | Then you can use grep, ls, etc | spockz wrote: | Has anyone tried whether this will give you build performance | benefits if you put your application source and/or dependencies | on this fs? | | I've played with ramdisk before but didn't notice any | difference, probably due the fs cache. | pmarreck wrote: | How would you defrag the sqlite file? Or would VACUUM or what | have you automagically accomplish that? | | Actually, having a sqlite filesystem is intriguing because you | could in theory add any kind of metadata or filesystem feature | you wanted to (such as a forward-error-correcting checksum | field, auto-compressed/decompressed data, dedup, encryption, | etc.) It would make it nearly trivial for anyone to experiment | with new filesystems. | ape4 wrote: | I don't know, maybe: `touch /mnt/sqlite/.vacuum` could be | setup to vacuum? | BenjiWiebe wrote: | Why not hook into fstrim for that? | tyho wrote: | Go is perhaps not the best tool to use for this as calling sqlite | via Cgo will incur a penalty. Might be significant in a very hot | loop. | christophilus wrote: | Go's the tool I'm using to build a side project, so I was | really only curious about Go + SQLite vs Go + file system. | jchw wrote: | You might find these projects interesting: | | - https://pkg.go.dev/modernc.org/ql | | - https://pkg.go.dev/modernc.org/sqlite | | It's hard to find much information about them, but the first | one seems to be a database similar to sqlite, and the latter | seems to be some kind of automated translation of sqlite to | Go. I'm not sure either of these will outperform sqlite on | CGo, but both of them should eliminate the CGo overhead and | might give you some more room. | | P.S.: The latter is a bit unorthodox in that it contains | separate code for each architecture supported by Go, most | likely a reflection of the method of the automated | translation. | christophilus wrote: | I hadn't heard of ql, but I tried the latter project, and | it was much slower for inserts. Something like 500/second. | chakkepolja wrote: | depending on your data, there's also Keyvalue stores like | boltdb & badger. | derefr wrote: | I believe https://github.com/erthink/libmdbx is the | highest-throughput transactional KV store with a Golang | binding right now. (It's the current storage backend for | https://github.com/ledgerwatch/erigon, which switches | quickly to whatever wacky library is optimally performant | at the moment.) ___________________________________________________________________ (page generated 2022-02-12 23:00 UTC)