SQLite 3.33
sqlite.org
sqlite.org
I asked about this on the SQLite forum and D. Richard Hipp said "This change was in response to a customer request. They still have a factor of 4 before reaching the old upper limit, but asked for additional headroom." https://sqlite.org/forum/forumpost/8e40a7f588428077d7f073c00...
We haven't broken the 100GB barrier for a single SQLite database file yet, but we have strong confidence that everything will simply continue working as expected once we do.
find / -name *.sqlite -printf '%s %p\n' 2>/dev/null | sort -nr | head -n 1
The winner is `favicons.sqlite` from Firefox profile directory, which is 40 MB.
https://github.com/mackyle/sqlite/blob/3cf493d4018042c70a4db...
mdfind "kMDItemDisplayName == *.sqlite" -0 | xargs -0 stat "-f%z %N" | sort -nr | head -n 5
should be fairly fast because mdfind uses the spotlight backend and already has this data cached.
What exactly do you mean by split it to several databases? It seems like to me that would make backup and replication and such more difficult, since now I'd have to manage multiple databases. But I don't have experience there, so I'd love to hear if there are easy ways to do that
Back in 2010 I thought yeah soon we will have 50TB hard drives then 500TB and someday I can have 1PB it will be all I will need! Sadly no such change. I would be happy to be in the 10s of TBs rage for under 200 dollars.
Games are getting stupid wasteful. Someone told me Fortnite is almost 90GB or so and I flinched considering GTA5 is around that range and offers a loooot more rich gameplay and features! What a wasteful game resource wise.
https://gta.fandom.com/wiki/Updates_in_GTA_Online (37 total)
In the case of GTA I’d imagine the voice lines are a major source of size as well. They’ve been doing updates for the online with new missions and voice lines for ages.
You can have a 1PB file without a 1PB drive. I think md has a limit of 8 Zib. Several filesystems allow files up to 8EB.
It depends on the size of the eggs though. With 1 PB drives will probably come 3D 360° wat K videos in which you can take a walk, and video games.
These videos will be downloaded from your crappy rural TB connection by the way. Web pages will still be slow as fuck to load, like today, because we will have figured out that downloading the entire NPM registry several times per page load is easier than taking the time to bundle the dependencies, and optimizing image and video size will be considered as a premature optimization that nobody does anymore.
The overhead (depends on partition/filesystem/etc layout) would probably take that under 281TB.
Adding a few more drives would still probably be needed to hold the file, and add some level of redundancy. :)
My first hard drive was an 8" 20MB drive. That's about 9.5 x 4.6 x 14.2 inches and weighed about 20 pounds. Only cost me $6000, in 1981. And with that massive capacity, I never did run out of room.
Now I have a 200GB MicroSD in my phone. It cost $75. Haven't run out of room on that one either.
I bet it's not SQLite's problem.
One poor woman I worked with used to come in every day and kick off a bunch of queries that would do a couple linear scan of a database and take four-six hours to complete. I added a single one column index and the same query ran in less then a second. Got a hug on the spot. The DBA was upset the backup took a couple minutes longer to complete but when he complained he got into trouble for not profiling the queries and adding the index himself (ha!).
After that I started using SQLite for a lot of things - instead of confronting the DBAs I’d just dump the official database into an SQLite database and run all my queries against that. Was kind of amazing that you would have these huge Oracle clusters supporting a database with a few tens or hundreds of megabytes (not even gigabytes) of data but perfect size for slurping into SQLite on my desktop.
My guess is that you were dealing with a person who may not actually enjoy their work and is optimizing to make their work as little as possible — but of course I may be way off course here. :)
It sounds like he doesn’t have the organization’s best interests in mind, but rather just his own.
> SQLite was originally designed with a policy of avoiding arbitrary limits. [...] Unfortunately, the no-limits policy has been shown to create problems. Because the upper bounds were not well defined, they were not tested, and bugs were often found when pushing SQLite to extremes.
Though I shudder to imagine the effort that goes into testing a 281 TB database.
Do they purchase all those hard drives and make one enormous RAID concatenated disk set? Or is there a way to more cheaply virtualize that by combining a bunch of max-sized 16 TB AWS EBS instances? What types of errors are even likely to come up at that point -- errors in SQLite's internal logic, or errors in the operating system or drivers?
You might find it interesting to look at the actual sqlite source commits where this change was introduced: https://sqlite.org/src/timeline?r=larger-databases It turns out the number comes from having a max of 2^32 pages in their database. Their default page being 4 kB each: https://www.sqlite.org/pgszchng2016.html
Working backwards, they must have raised it to 64kb: `python -c 'print(1024 * 64 * 232)'` produces 281,474,976,710,656.
We also have a simple utility program in the SQLite source tree (https://www.sqlite.org/src/file/tool/enlargedb.c) that lets you create a massive database file using a sparse file (https://en.wikipedia.org/wiki/Sparse_file) on systems that support that kind of thing.
Or the authors want to provide some guaranties and upper limits are set according to what is known to work / tested.
I'd be interested in knowing the actual answer to your question though.
edit: the actual answer is in the sibling comment, ah ah.
Many interpreters let you use a column alias from the select clause in the group and order clauses. This has better readability IMO but I'm not sure it's in the SQL-92 standard, but I believe it is now standardized.
Not sure if it's standardised, but Postgres doesn't let you do this (rather irritatingly).
It's tedious that all this is hearsay without open access standards. It's "only" $195 for the latest.
> An expression used inside a grouping_element can be an input column name, or the name or ordinal number of an output column (SELECT list item), or an arbitrary expression formed from input-column values. [0]
> Each expression can be the name or ordinal number of an output column (SELECT list item), or it can be an arbitrary expression formed from input-column values. [1]
Perhaps you are thinking of trying to use an output column name in a WHERE clause?
[0]: https://www.postgresql.org/docs/current/sql-select.html#SQL-...
[1]: https://www.postgresql.org/docs/current/sql-select.html#SQL-...
Yeah, I think I am thinking about this.
Its pretty frustrating because the actual query engine is perfectly capable of executing fairly complex SQL expressions efficiently (they're not really that complex computationally, but they are syntactically because of SQL's verbosity), but the code becomes quite unmaintainable if you use too many of them.
For example, the following expression:
ROUND((
(EXTRACT(EPOCH FROM (s.end_time - s.start_time)) / 60) -- Shift length in minutes
- (FLOOR((EXTRACT(EPOCH FROM (s.end_time - s.start_time)) / 60) / 380) * 20) -- Break length in minutes
)::numeric / 60 , 2) as hours_planned,
It repeats the sub-expression `EXTRACT(EPOCH FROM (s.end_time - s.start_time)) / 60)`. If I could name that sub expression and reference it multiple times then the overall expression would be a lot more readable.Edit: Or use subqueries apparently.
Agreed, but the purpose of the example is to demonstrate how to use UPDATE FROM, nothing more. I appreciate how it accomplishes a complex update in a very clear, concise, elegant way.
Yeah![1] with some caveats, that also apply to the sqlite implementation if im not mistaken:
When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the from_item list, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.
They have add, sub, mul and sum functions for text strings as well as comparison.
I have a lot of stuff dancing around the lacking of decimals in sqlite, so this is so welcoming!
UPDATE inventory
SET quantity = quantity - daily.amt
FROM (SELECT sum(quantity) AS amt, itemId FROM sales GROUP BY 2) AS daily
WHERE inventory.itemId = daily.itemId;
Could be done with MERGE using: MERGE INTO inventory i
USING (
SELECT
SUM(quantity) AS amt
, itemId
FROM sales
GROUP BY 2
) daily
ON (
i.itemId = daily.itemId
)
WHEN MATCHED THEN UPDATE
SET i.quantity = i.quantity - daily.amt;This question is purely around INSERTS - no UPDATES.
Anything I should be aware of? Looking to write data from multiple services to an SQLite file.
> Multiple processes can have the same database open at the same time. Multiple processes can be doing a SELECT at the same time. But only one process can be making changes to the database at any moment in time, however.
Sounds like you can, just not at the same moment as it locks the file during writes. It appears to retry if the file is locked, so not the end of the world.
Faq- https://www.sqlite.org/faq.html#q5
Relevant SO post - https://stackoverflow.com/questions/15383615/multiple-access...
It's perfectly ok to write to sqlite from different processes in the same time, but to achieve good results it's better to:
* use WAL mode - so the readers and writers do not block (you can turn on it with `PRAGMA journal_mode=WAL;` in CLI, and it's better to add `PRAGMA main.synchronous=NORMAL;` also).
* all concurrent writes will be queued by sqlite3 lib and done in sequential manner, and if any write attempt will wait longer that BUSY_TIMEOUT ( see https://www.sqlite.org/pragma.html#pragma_busy_timeout ) , it will return error.
Snippet
# setting things up...
itroot@l7490:/tmp$ grep -i pragma ~/.sqliterc
PRAGMA journal_mode=WAL;
PRAGMA main.synchronous=NORMAL;
PRAGMA busy_timeout=1000;
itroot@l7490:/tmp$ sqlite3 test.sqlite 'CREATE TABLE records (id INTEGER PRIMARY KEY, record TEXT);' > /dev/null 2>&1
# running 10 parallel processes that inserts numbers from 1 to 1000...
itroot@l7490:/tmp$ echo {1..1000} | xargs -n1 -d' ' -P 10 -i% sqlite3 test.sqlite 'INSERT INTO records (record) VALUES (%);' >/dev/null 2>&1
# getting number of records
itroot@l7490:/tmp$ sqlite3 test.sqlite 'SELECT count(*) FROM records;'
count(*) = 1000I wish WAL mode were the default. I wish read only WAL mode were easier to do without putting the database file in a sticky directory. Oh well.
The web server runs unprivileged and only needs read permission. Insert and vacuum are done as a user which has write permission.
The documentation says read only WAL mode is possible if there is write permission on the directory. So I put the database file in its own directory and set the mode of the database file to 0664 and set the mode of the directory to 3777. So an unprivileged process has permission to create WAL files which become group writable.
UPDATE inventory
SET quantity = inventory.quantity - daily.amt
FROM
(SELECT sum(quantity) AS amt, itemId FROM sales GROUP BY 2) daily USING( itemId );
Basically just allowing a ON/USING clause after the first FROM entry as if it was joining to the table being updated.Otherwise it's kind of annoying when you end up joining to several tables in the update, but have to use the WHERE clause to join back to the main table.
UPDATE inventory
INNER JOIN (SELECT sum(quantity) AS amt, itemId FROM sales GROUP BY 2) AS daily USING (itemId)
SET quantity = quantity - daily.amt;
I had thought postgres could do it this way without the extra FROM syntax, but apparently not.CQRS overused a lot though, like using a $75k surveillance robotic dog from Boston Dynamics [https://spectrum.ieee.org/automaton/robotics/industrial-robo...] (Massive Dynamics?) to see who's at the door, when you could have just looked through the peephole.
I could see this feature becoming the CQRS of the SQL world for a while, used in many places where it should be considered harmful, in addition to the places where it is helpful.
I’d expect a CQRS system on top of SQL to be implemented using a single event table and a lot of triggers, each triggering a different aggregate.
The reason I noted how it's great for CQRS is that I've usually seen CQRS implemented with two data models. One is queried, and one is modified via commands. The one that's queried is updated according to some strategy, sometimes on an event triggered by the command model being modified. This this you could trigger and update on your query model when your command model is changed, all within SQL.
* It's only about CQRS, which in no way was mentioned in the article;
* You're not properly qualifying why this feature is so important for CQRS;
* In the same breath, you're also claiming it's overused and complex, while in fact you're the one who's "promoting" it.
I agree that in my reply, I was actually thinking about ES + CQRS rather than pure CQRS, but the gist of my comment still stands: I would expect a CQRS implementation to work with triggers (for incremental updates) or materialized views (one table insert-only, the "view" is kept in sync automatically by the database, which is what users query). Could you elaborate on why you think this new feature is better than those two approaches?