Skip to content

Commit b9d531a

Browse files
committed
make block size configurable
1 parent f70fcbe commit b9d531a

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

libsql-sqlite3/src/vectorIndex.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -383,18 +383,19 @@ static struct VectorColumnType VECTOR_COLUMN_TYPES[] = {
383383
struct VectorParamName {
384384
const char *zName;
385385
int tag;
386-
int type; // 0 - enum, 1 - integer, 2 - float
386+
int type; // 0 - string enum, 1 - integer, 2 - float
387387
const char *zValueStr;
388388
u64 value;
389389
};
390390

391391
static struct VectorParamName VECTOR_PARAM_NAMES[] = {
392-
{ "type", VECTOR_INDEX_TYPE_PARAM_ID, 0, "diskann", VECTOR_INDEX_TYPE_DISKANN },
393-
{ "metric", VECTOR_METRIC_TYPE_PARAM_ID, 0, "cosine", VECTOR_METRIC_TYPE_COS },
394-
{ "metric", VECTOR_METRIC_TYPE_PARAM_ID, 0, "l2", VECTOR_METRIC_TYPE_L2 },
395-
{ "alpha", VECTOR_PRUNING_ALPHA_PARAM_ID, 2, 0, 0 },
396-
{ "search_l", VECTOR_SEARCH_L_PARAM_ID, 1, 0, 0 },
397-
{ "insert_l", VECTOR_INSERT_L_PARAM_ID, 2, 0, 0 },
392+
{ "type", VECTOR_INDEX_TYPE_PARAM_ID, 0, "diskann", VECTOR_INDEX_TYPE_DISKANN },
393+
{ "metric", VECTOR_METRIC_TYPE_PARAM_ID, 0, "cosine", VECTOR_METRIC_TYPE_COS },
394+
{ "metric", VECTOR_METRIC_TYPE_PARAM_ID, 0, "l2", VECTOR_METRIC_TYPE_L2 },
395+
{ "alpha", VECTOR_PRUNING_ALPHA_PARAM_ID, 2, 0, 0 },
396+
{ "search_l", VECTOR_SEARCH_L_PARAM_ID, 1, 0, 0 },
397+
{ "insert_l", VECTOR_INSERT_L_PARAM_ID, 1, 0, 0 },
398+
{ "max_edges", VECTOR_MAX_EDGES_PARAM_ID, 1, 0, 0 },
398399
};
399400

400401
static int parseVectorIdxParam(const char *zParam, VectorIdxParams *pParams, const char **pErrMsg) {
@@ -414,11 +415,15 @@ static int parseVectorIdxParam(const char *zParam, VectorIdxParams *pParams, con
414415
continue;
415416
}
416417
if( VECTOR_PARAM_NAMES[i].type == 1 ){
417-
u64 value = sqlite3Atoi(zValue);
418+
int value = sqlite3Atoi(zValue);
418419
if( value == 0 ){
419420
*pErrMsg = "invalid representation of integer vector index parameter";
420421
return -1;
421422
}
423+
if( value < 0 ){
424+
*pErrMsg = "integer vector index parameter must be positive";
425+
return -1;
426+
}
422427
if( vectorIdxParamsPutU64(pParams, VECTOR_PARAM_NAMES[i].tag, value) != 0 ){
423428
*pErrMsg = "unable to serialize integer vector index parameter";
424429
return -1;

libsql-sqlite3/src/vectorIndexInt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ typedef u8 MetricType;
130130
#define VECTOR_SEARCH_L_PARAM_ID 9
131131
#define VECTOR_SEARCH_L_DEFAULT 200
132132

133+
#define VECTOR_MAX_EDGES_PARAM_ID 10
134+
133135
/* total amount of vector index parameters */
134136
#define VECTOR_PARAM_IDS_COUNT 9
135137

libsql-sqlite3/src/vectordiskann.c

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
*/
5050
#ifndef SQLITE_OMIT_VECTOR
5151

52+
#include "math.h"
5253
#include "sqliteInt.h"
5354
#include "vectorIndexInt.h"
5455

@@ -64,6 +65,11 @@
6465
// stack simplify memory managment code and also doesn't impose very strict limits here since 128 bytes for column names should be enough for almost all use cases
6566
#define DISKANN_SQL_RENDER_LIMIT 128
6667

68+
// limit to the maximum size of DiskANN block (128 MB)
69+
// even with 1MB we can store tens of thousands of nodes in several GBs - which is already too much
70+
// but we are "generous" here and allow user to store up to 128MB blobs
71+
#define DISKANN_MAX_BLOCK_SZ 134217728
72+
6773
/*
6874
* Due to historical reasons parameter for index block size were stored as u16 value and divided by 512 (2^9)
6975
* So, we will make inverse transform before initializing index from stored parameters
@@ -263,8 +269,16 @@ void blobSpotFree(BlobSpot *pBlobSpot) {
263269
** Layout specific utilities
264270
**************************************************************************/
265271

272+
int nodeEdgeOverhead(int nEdgeVectorSize){
273+
return nEdgeVectorSize + VECTOR_EDGE_METADATA_SIZE;
274+
}
275+
276+
int nodeOverhead(int nNodeVectorSize){
277+
return nNodeVectorSize + VECTOR_NODE_METADATA_SIZE;
278+
}
279+
266280
int nodeEdgesMaxCount(const DiskAnnIndex *pIndex){
267-
unsigned int nMaxEdges = (pIndex->nBlockSize - pIndex->nNodeVectorSize - VECTOR_NODE_METADATA_SIZE) / (pIndex->nEdgeVectorSize + VECTOR_EDGE_METADATA_SIZE);
281+
unsigned int nMaxEdges = (pIndex->nBlockSize - nodeOverhead(pIndex->nNodeVectorSize)) / nodeEdgeOverhead(pIndex->nEdgeVectorSize);
268282
assert( nMaxEdges > 0);
269283
return nMaxEdges;
270284
}
@@ -419,6 +433,8 @@ int diskAnnCreateIndex(
419433
VectorIdxParams *pParams
420434
){
421435
int rc;
436+
int type, dims;
437+
u64 maxEdgesParam, blockSizeBytes;
422438
char *zSql;
423439
char columnSqlDefs[DISKANN_SQL_RENDER_LIMIT]; // definition of columns (e.g. index_key INTEGER BINARY, index_key1 TEXT, ...)
424440
char columnSqlNames[DISKANN_SQL_RENDER_LIMIT]; // just column names (e.g. index_key, index_key1, index_key2, ...)
@@ -431,16 +447,34 @@ int diskAnnCreateIndex(
431447
if( vectorIdxParamsPutU64(pParams, VECTOR_INDEX_TYPE_PARAM_ID, VECTOR_INDEX_TYPE_DISKANN) != 0 ){
432448
return SQLITE_ERROR;
433449
}
450+
type = vectorIdxParamsGetU64(pParams, VECTOR_TYPE_PARAM_ID);
451+
if( type == 0 ){
452+
return SQLITE_ERROR;
453+
}
454+
dims = vectorIdxParamsGetU64(pParams, VECTOR_DIM_PARAM_ID);
455+
if( dims == 0 ){
456+
return SQLITE_ERROR;
457+
}
458+
assert( 0 < dims && dims <= MAX_VECTOR_SZ );
459+
460+
maxEdgesParam = vectorIdxParamsGetU64(pParams, VECTOR_MAX_EDGES_PARAM_ID);
461+
if( maxEdgesParam == 0 ){
462+
// 3 D**(1/2) gives good recall values (90%+)
463+
// we also want to keep disk overhead at moderate level - 50x of the disk size increase is the current upper bound
464+
maxEdgesParam = MIN(3 * ((int)(sqrt(dims)) + 1), (50 * nodeOverhead(vectorDataSize(type, dims))) / nodeEdgeOverhead(vectorDataSize(type, dims)) + 1);
465+
}
466+
blockSizeBytes = nodeOverhead(vectorDataSize(type, dims)) + maxEdgesParam * (u64)nodeEdgeOverhead(vectorDataSize(type, dims));
467+
if( blockSizeBytes > DISKANN_MAX_BLOCK_SZ ){
468+
return SQLITE_ERROR;
469+
}
470+
if( vectorIdxParamsPutU64(pParams, VECTOR_BLOCK_SIZE_PARAM_ID, MAX(256, blockSizeBytes)) != 0 ){
471+
return SQLITE_ERROR;
472+
}
434473
if( vectorIdxParamsGetU64(pParams, VECTOR_METRIC_TYPE_PARAM_ID) == 0 ){
435474
if( vectorIdxParamsPutU64(pParams, VECTOR_METRIC_TYPE_PARAM_ID, VECTOR_METRIC_TYPE_COS) != 0 ){
436475
return SQLITE_ERROR;
437476
}
438477
}
439-
if( vectorIdxParamsGetU64(pParams, VECTOR_BLOCK_SIZE_PARAM_ID) == 0 ){
440-
if( vectorIdxParamsPutU64(pParams, VECTOR_BLOCK_SIZE_PARAM_ID, VECTOR_BLOCK_SIZE_DEFAULT) != 0 ){
441-
return SQLITE_ERROR;
442-
}
443-
}
444478
if( vectorIdxParamsGetF64(pParams, VECTOR_PRUNING_ALPHA_PARAM_ID) == 0 ){
445479
if( vectorIdxParamsPutF64(pParams, VECTOR_PRUNING_ALPHA_PARAM_ID, VECTOR_PRUNING_ALPHA_DEFAULT) != 0 ){
446480
return SQLITE_ERROR;
@@ -1430,6 +1464,7 @@ int diskAnnOpenIndex(
14301464
DiskAnnIndex **ppIndex /* OUT: Index */
14311465
){
14321466
DiskAnnIndex *pIndex;
1467+
u64 nBlockSize;
14331468
pIndex = sqlite3DbMallocRaw(db, sizeof(DiskAnnIndex));
14341469
if( pIndex == NULL ){
14351470
return SQLITE_NOMEM;
@@ -1442,9 +1477,15 @@ int diskAnnOpenIndex(
14421477
diskAnnCloseIndex(pIndex);
14431478
return SQLITE_NOMEM_BKPT;
14441479
}
1480+
nBlockSize = vectorIdxParamsGetU64(pParams, VECTOR_BLOCK_SIZE_PARAM_ID);
1481+
// preserve backward compatibility: treat block size > 128 literally, but <= 128 with shift
1482+
if( nBlockSize <= 128 ){
1483+
nBlockSize <<= DISKANN_BLOCK_SIZE_SHIFT;
1484+
}
1485+
14451486
pIndex->nFormatVersion = vectorIdxParamsGetU64(pParams, VECTOR_FORMAT_PARAM_ID);
14461487
pIndex->nDistanceFunc = vectorIdxParamsGetU64(pParams, VECTOR_METRIC_TYPE_PARAM_ID);
1447-
pIndex->nBlockSize = vectorIdxParamsGetU64(pParams, VECTOR_BLOCK_SIZE_PARAM_ID) << DISKANN_BLOCK_SIZE_SHIFT;
1488+
pIndex->nBlockSize = nBlockSize;
14481489
pIndex->nNodeVectorType = vectorIdxParamsGetU64(pParams, VECTOR_TYPE_PARAM_ID);
14491490
pIndex->nVectorDims = vectorIdxParamsGetU64(pParams, VECTOR_DIM_PARAM_ID);
14501491
pIndex->pruningAlpha = vectorIdxParamsGetF64(pParams, VECTOR_PRUNING_ALPHA_PARAM_ID);

0 commit comments

Comments
 (0)