-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ENH] add vacuum CLI command #2519
Conversation
Reviewer ChecklistPlease leverage this checklist to ensure your code review is thorough before approving Testing, Bugs, Errors, Logs, Documentation
System Compatibility
Quality
|
@@ -19,6 +19,7 @@ posthog>=2.4.0 | |||
pydantic>=1.9 | |||
pypika>=0.48.9 | |||
PyYAML>=6.0.0 | |||
rich>=10.11.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rich was already a subdependency of typer, so this is not a new dependency
id INT PRIMARY KEY, | ||
timestamp INT NOT NULL, | ||
operation TEXT NOT NULL | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may be useful in the future, but currently only used for assertions in tests
chromadb/cli/cli.py
Outdated
raise typer.Exit(code=1) | ||
|
||
if not force and not typer.confirm( | ||
"Are you sure you want to vacuum the database? This will block both reads and writes to the database, and may take a while." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VACUUM can be safely run with concurrent users (e.g. the chroma server running) but will block all queries as it takes an exclusive lock
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For very large DBs this can take up to a min or more. There are at least two options here:
conn.execute('PRAGMA busy_timeout = 5000')
- https://www.sqlite.org/c3ref/busy_timeout.html- using WAL mode, although, this may not play nicely with
VACUUM into
In prior implementations I did force the whole connection pool to close all connections and do a global lockout to ensure no incoming requests are processed, but for that to work this command needs to execute within the fastapi process/worker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, not clear to me what your comment is addressing, why would we want to enable WAL mode on SQLite?
I do change the busy_timeout before running VACUUM just so that it's not indefinitely blocked by long-running writes (our global timeout is set to 16m currently).
settings.persist_directory = path | ||
system = System(settings=settings) | ||
sqlite = system.instance(SqliteDB) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to add a check before vacuuming that there's enough free disk space (> current db size) but this turned out to be fairly difficult:
- SQLite doesn't directly expose its temporary directory (or at least the PRAGMA that does is deprecated)
- how would we set up tests to simulate a mount point running out of space?
If the vacuum does fail because there's not enough space, that error will propagate back to stdout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@codetheweb, here are some thoughts:
- You can vacuum into a new file
VACUUM into <file>
- this mimics copy on write, which I think might be a good fit here as we control where things go and how we do checks. This will not work if the DB is live, though, as files need to be moved/removed. - As far as testing goes, it could do the trick of restricting space in a docker test.
services:
chroma:
image: chroma
tmpfs:
- /chroma/chroma:size=100M
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can vacuum into a new file VACUUM into - this mimics copy on write, which I think might be a good fit here as we control where things go and how we do checks. This will not work if the DB is live, though, as files need to be moved/removed.
I think the fact that this puts the correctness burden on us makes it a dealbreaker.
In practice I'm not sure if this will be a real issue; if the WAL is pruned prior to VACUUM in theory the amount of temporary space needed should be much less than the current database size; assuming the size of most databases is dominated by the WAL.
In one of the prior incarnations of this, we also reported on the stats of what the vacuum did, e.g., the size of the SQLite3 file before/after and, optionally, the number of free_pages before/after. This could be good information to help users understand the effects of vacuuming. |
We could expose this in the future, but I don't see this being particularly useful right now as vacuum operations after the initial one aren't expected to free much space. People can always do |
I do think it's useful to tell users what the very first vacuum did for them, and then if they try doing it again when they don't need to, to see that it does not do much for them. |
|
0d57374
to
2b61a2b
Compare
This stack of pull requests is managed by Graphite. Learn more about stacking. Join @codetheweb and the rest of your teammates on Graphite |
0738955
to
33e05bb
Compare
80922a6
to
20af104
Compare
ccc8bfd
to
be8dffc
Compare
da94fa7
to
f31e637
Compare
c4fc599
to
c907d7a
Compare
f31e637
to
5fce360
Compare
5fce360
to
37c17eb
Compare
Merge activity
|
Implementation of the CLI command described in this CIP: #2498. Terminal UI demo:
Screen.Recording.2024-07-24.at.4.48.03.PM.mov
Warning that's logged when automatic pruning is disabled: