mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 12:07:34 +08:00
Compare commits
3 Commits
v0.6.1
...
hnsw-debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb2782c9f6 | ||
|
|
62350b1589 | ||
|
|
dd57309281 |
@@ -581,6 +581,10 @@ or choose to store vectors inline:
|
|||||||
ALTER TABLE items ALTER COLUMN embedding SET STORAGE PLAIN;
|
ALTER TABLE items ALTER COLUMN embedding SET STORAGE PLAIN;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Why are there less results for a query after adding an HNSW index?
|
||||||
|
|
||||||
|
Results are limited by the size of the dynamic candidate list (`hnsw.ef_search`). There may be even less results due to dead tuples or filtering conditions in the query. We recommend setting `hnsw.ef_search` to at least twice the `LIMIT` of the query. If you need more than 500 results, use an IVFFlat index instead.
|
||||||
|
|
||||||
#### Why are there less results for a query after adding an IVFFlat index?
|
#### Why are there less results for a query after adding an IVFFlat index?
|
||||||
|
|
||||||
The index was likely created with too little data for the number of lists. Drop the index until the table has more data.
|
The index was likely created with too little data for the number of lists. Drop the index until the table has more data.
|
||||||
@@ -589,6 +593,8 @@ The index was likely created with too little data for the number of lists. Drop
|
|||||||
DROP INDEX index_name;
|
DROP INDEX index_name;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Results can also be limited by the number of probes (`ivfflat.probes`).
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
### Vector Type
|
### Vector Type
|
||||||
|
|||||||
24
src/hnsw.c
24
src/hnsw.c
@@ -17,7 +17,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int hnsw_ef_search;
|
int hnsw_ef_search;
|
||||||
int hnsw_lock_tranche_id;
|
int hnsw_entry_lock_tranche_id;
|
||||||
|
int hnsw_allocator_lock_tranche_id;
|
||||||
|
int hnsw_flush_lock_tranche_id;
|
||||||
|
int hnsw_element_lock_tranche_id;
|
||||||
static relopt_kind hnsw_relopt_kind;
|
static relopt_kind hnsw_relopt_kind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -36,16 +39,27 @@ HnswInitLockTranche(void)
|
|||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
||||||
tranche_ids = ShmemInitStruct("hnsw LWLock ids",
|
tranche_ids = ShmemInitStruct("hnsw LWLock ids v2",
|
||||||
sizeof(int) * 1,
|
sizeof(int) * 4,
|
||||||
&found);
|
&found);
|
||||||
if (!found)
|
if (!found)
|
||||||
|
{
|
||||||
tranche_ids[0] = LWLockNewTrancheId();
|
tranche_ids[0] = LWLockNewTrancheId();
|
||||||
hnsw_lock_tranche_id = tranche_ids[0];
|
tranche_ids[1] = LWLockNewTrancheId();
|
||||||
|
tranche_ids[2] = LWLockNewTrancheId();
|
||||||
|
tranche_ids[3] = LWLockNewTrancheId();
|
||||||
|
}
|
||||||
|
hnsw_entry_lock_tranche_id = tranche_ids[0];
|
||||||
|
hnsw_allocator_lock_tranche_id = tranche_ids[1];
|
||||||
|
hnsw_flush_lock_tranche_id = tranche_ids[2];
|
||||||
|
hnsw_element_lock_tranche_id = tranche_ids[3];
|
||||||
LWLockRelease(AddinShmemInitLock);
|
LWLockRelease(AddinShmemInitLock);
|
||||||
|
|
||||||
/* Per-backend registration of the tranche ID */
|
/* Per-backend registration of the tranche ID */
|
||||||
LWLockRegisterTranche(hnsw_lock_tranche_id, "HnswBuild");
|
LWLockRegisterTranche(hnsw_entry_lock_tranche_id, "HnswEntry");
|
||||||
|
LWLockRegisterTranche(hnsw_allocator_lock_tranche_id, "HnswAllocator");
|
||||||
|
LWLockRegisterTranche(hnsw_flush_lock_tranche_id, "HnswFlush");
|
||||||
|
LWLockRegisterTranche(hnsw_element_lock_tranche_id, "HnswElement");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -113,7 +113,10 @@
|
|||||||
|
|
||||||
/* Variables */
|
/* Variables */
|
||||||
extern int hnsw_ef_search;
|
extern int hnsw_ef_search;
|
||||||
extern int hnsw_lock_tranche_id;
|
extern int hnsw_entry_lock_tranche_id;
|
||||||
|
extern int hnsw_allocator_lock_tranche_id;
|
||||||
|
extern int hnsw_flush_lock_tranche_id;
|
||||||
|
extern int hnsw_element_lock_tranche_id;
|
||||||
|
|
||||||
typedef struct HnswElementData HnswElementData;
|
typedef struct HnswElementData HnswElementData;
|
||||||
typedef struct HnswNeighborArray HnswNeighborArray;
|
typedef struct HnswNeighborArray HnswNeighborArray;
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heaptid, Hn
|
|||||||
HnswPtrStore(base, element->value, valuePtr);
|
HnswPtrStore(base, element->value, valuePtr);
|
||||||
|
|
||||||
/* Create a lock for the element */
|
/* Create a lock for the element */
|
||||||
LWLockInitialize(&element->lock, hnsw_lock_tranche_id);
|
LWLockInitialize(&element->lock, hnsw_element_lock_tranche_id);
|
||||||
|
|
||||||
/* Insert tuple */
|
/* Insert tuple */
|
||||||
InsertTupleInMemory(buildstate, element);
|
InsertTupleInMemory(buildstate, element);
|
||||||
@@ -611,9 +611,9 @@ InitGraph(HnswGraph * graph, char *base, long memoryTotal)
|
|||||||
graph->flushed = false;
|
graph->flushed = false;
|
||||||
graph->indtuples = 0;
|
graph->indtuples = 0;
|
||||||
SpinLockInit(&graph->lock);
|
SpinLockInit(&graph->lock);
|
||||||
LWLockInitialize(&graph->entryLock, hnsw_lock_tranche_id);
|
LWLockInitialize(&graph->entryLock, hnsw_entry_lock_tranche_id);
|
||||||
LWLockInitialize(&graph->allocatorLock, hnsw_lock_tranche_id);
|
LWLockInitialize(&graph->allocatorLock, hnsw_allocator_lock_tranche_id);
|
||||||
LWLockInitialize(&graph->flushLock, hnsw_lock_tranche_id);
|
LWLockInitialize(&graph->flushLock, hnsw_flush_lock_tranche_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user