Repository navigation
Conversation
When the medoid was deleted, diskann_medoid_handle_delete() took the first other rowid of _vectorsNN as the new one, which can be a vector still waiting in the buffer, with no node: every search then started from a node it could not read, found nothing in the graph, and returned only the buffer until the next flush. The replacement is now the first other node of _diskann_nodesNN, and a failed step of that query is returned instead of emptying the graph's medoid.
This was referenced Oct 23, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deleting a DiskANN column's medoid while rows wait in its buffer leaves the graph unsearchable until the buffer is flushed.
diskann_medoid_handle_delete()picks the new medoid withSELECT rowid FROM _vectorsNN WHERE rowid != ?1 LIMIT 1. Withbuffer_thresholdset,_vectorsNNalso holds the buffered rows, which have no node yet, and the lowest rowid can be one of them. Every search then starts from a nodediskann_search()cannot read: the loop skips it and ends, the graph contributes no rows, and the KNN query returns only what the buffer scan finds.On main, after that delete, none of the 9 remaining nodes is returned by a
k = 1query with its own vector, for each of eight random tables. Here, the new medoid is the first other node of_diskann_nodesNN, so it is always a node of the graph, and all 9 are found in each of them. When no node is left, the medoid is set to empty as before. A failed step of that query is now returned, where it used to set the medoid to empty as well.test_diskann_delete_medoid_with_rows_in_bufferin test-diskann.py fails on main and passes here; the Python suite passes (240 passed, 66 skipped), test-diskann.py passes against an AddressSanitizer and UndefinedBehaviorSanitizer build, and the build's warnings are main's. The test uses the int8 quantizer: under the binary quantizer a query can also lose its own row to one whose quantized distance ties it, which #345 fixes.It merges cleanly with every open PR that touches the DiskANN code, #344 and #345 included.
Origin. Found in the DiskANN port to photostructure/sqlite-vec, photostructure#11 (cd53413), which lists it among the port's differences from upstream; the change and its test are written here for asg017's main. No open or closed PR or issue here makes the same change.