rename qdrant-client (#128)

* rename qdrant-client

* docs auto-sync

---------

Co-authored-by: qdrant <qdrant@users.noreply.github.com>
This commit is contained in:
Andrey Vasnetsov
2023-03-30 22:04:44 +02:00
committed by GitHub
co-authored by qdrant
parent b10cd0ddd5
commit f1d8084f70
5 changed files with 42 additions and 55 deletions
@@ -350,14 +350,14 @@ However, in some cases, it is necessary to ensure additional guarantees during p
Qdrant provides a few options to control consistency guarantees:
- `write_concern_factor` - defines the number of replicas that must acknowledge a write operation before responding to the client. Increasing this value will make write operations tolerant to network partitions in the cluster, but will require a higher number of replicas to be active to perform write operations.
- `write_consistency_factor` - defines the number of replicas that must acknowledge a write operation before responding to the client. Increasing this value will make write operations tolerant to network partitions in the cluster, but will require a higher number of replicas to be active to perform write operations.
- Read `consistency` param, can be used with search and retrieve operations to ensure that the results obtained from all replicas are the same. If this option is used, qdrant will perform the read operation on multiple replicas and resolve the result according to the selected strategy. This option is useful to avoid data inconsistency in case of concurrent updates of the same documents. This options is preferred if the update operations are frequent and the number of replicas is low.
- Write `ordering` param, can be used with update and delete operations to ensure that the operations are executed in the same order on all replicas. If this option is used, qdrant will route the operation to the leader replica of the shard and wait for the response before responding to the client. This option is useful to avoid data inconsistency in case of concurrent updates of the same documents. This options is preferred if read operations are more frequent than update and if search performance is critical.
### Write concern factor
The `write_concern_factor` represents the number of replicas that must acknowledge a write operation before responding to the client. It is set to one by default.
The `write_consistency_factor` represents the number of replicas that must acknowledge a write operation before responding to the client. It is set to one by default.
It can be configured at the collection's creation time.
```http
@@ -370,7 +370,7 @@ PUT /collections/{collection_name}
},
"shard_number": 6,
"replication_factor": 2,
"write_concern_factor": 2,
"write_consistency_factor": 2,
}
```
@@ -385,11 +385,11 @@ client.recreate_collection(
vectors_config=models.VectorParams(size=300, distance=models.Distance.COSINE),
shard_number=6,
replication_factor=2,
write_concern_factor=2,
write_consistency_factor=2,
)
```
Write operations will fail if the number of active replicas is less than the `write_concern_factor`.
Write operations will fail if the number of active replicas is less than the `write_consistency_factor`.
### Read consistency
+29 -39
View File
@@ -4,8 +4,7 @@ weight: 130
---
This sections contains a collection of how-to guides and tutorials for different use cases of Qdrant.
This section contains a collection of how-to guides and tutorials for different use cases of Qdrant.
## Optimize qdrant
@@ -14,16 +13,15 @@ Qdrant is designed to be flexible and customizable so you can tune it to your ne
![Trafeoff](/docs/tradeoff.png)
Let's look deeper into each of those possible optimization scenarios.
### Prefer Low memory footprint with high speed search
### Prefer low memory footprint with high speed search
The main way to achieve high speed search with low memory footprint is keep vectors on disk at the same time minimizing number of disk reads.
The main way to achieve high speed search with low memory footprint is to keep vectors on disk while at the same time minimizing the number of disk reads.
Vector Quantization is one way to achieve this. Quantization converts vectors into a more compact representation, which can be stored in memory and used for search. With smaller vectors you can cache more in RAM and reduce number of disk reads.
Vector quantization is one way to achieve this. Quantization converts vectors into a more compact representation, which can be stored in memory and used for search. With smaller vectors you can cache more in RAM and reduce the number of disk reads.
To configure in-memory quantization, with on-disk original vectors, you need to create a collection with the following config:
To configure in-memory quantization, with on-disk original vectors, you need to create a collection with the following configuration:
```http
PUT /collections/{collection_name}
@@ -66,8 +64,7 @@ client.recreate_collection(
`mmmap_threshold` will ensure that vectors will be stored on disk, while `always_ram` will ensure that quantized vectors will be stored in RAM.
Optionally, you can disable rescoring with search `params`, which will reduce disk reads even further, but potentially slightly decrease precision.
Optionally, you can disable rescoring with search `params`, which will reduce the number of disk reads even further, but potentially slightly decrease the precision.
```http
POST /collections/{collection_name}/points/search
@@ -100,8 +97,7 @@ client.search(
)
```
### Prefer High precision with low memory footprint
### Prefer high precision with low memory footprint
In case you need high precision, but don't have enough RAM to store vectors in memory, you can enable on-disk vectors and HNSW index.
@@ -135,7 +131,7 @@ client.recreate_collection(
)
```
In this scenario you can increase precision of the search by increasing `ef` nad `m` parameter of HNSW index, even with limited RAM.
In this scenario you can increase the precision of the search by increasing the `ef` and `m` parameters of the HNSW index, even with limited RAM.
```
...
@@ -150,8 +146,7 @@ In this scenario you can increase precision of the search by increasing `ef` nad
The disk IOPS is a critical factor in this scenario, it will determine how fast you can perform search.
You can use [fio](https://gist.github.com/superboum/aaa45d305700a7873a8ebbab1abddf2b) to measure disk IOPS.
### Prefer High precision with high speed search
### Prefer high precision with high speed search
For high speed and high precision search it is critical to keep as much data in RAM as possible.
By default, Qdrant follows this approach, but you can tune it to your needs.
@@ -231,17 +226,16 @@ client.search(
- `hnsw_ef` - controls the number of neighbors to visit during search. The higher the value, the more accurate and slower the search will be. Recommended range is 32-512.
- `exact` - if set to `true`, will perform exact search, which will be slower, but more accurate. You can use it to compare results of the search with different `hnsw_ef` values versus the ground truth.
### Latency vs Throughput
- There are two main approaches to measure speed of search:
- latency of the request - time from the moment request is submitted to the moment response is received
- throughput - number of requests per second the system can handle
- There are two main approaches to measure the speed of search:
- latency of the request - the time from the moment request is submitted to the moment a response is received
- throughput - the number of requests per second the system can handle
This approach is not mutually exclusive, but in some cases it might be preferable to optimize for one or another.
Those approaches are not mutually exclusive, but in some cases it might be preferable to optimize for one or another.
To prefer minimizing latency, you can set up qdrant to use as many cores for the single request as possible.
You can do it by setting number of segments in the collection to be equal of a factor of the number of cores in the system. In this case, each segment will be processed in parallel, and the final result will be obtained faster.
To prefer minimizing latency, you can set up Qdrant to use as many cores as possible for a single request\.
You can do this by setting the number of segments in the collection to be equal to the number of cores in the system. In this case, each segment will be processed in parallel, and the final result will be obtained faster.
```http
@@ -270,10 +264,9 @@ client.recreate_collection(
)
```
To prefer throughput, you can set up qdrant to use as many cores as possible for processing multiple requests in parallel.
To prefer throughput, you can set up Qdrant to use as many cores as possible for processing multiple requests in parallel.
To do that, you can configure qdrant to use minimal number of segments, which is usually 2.
Large segments benefit from size of the index and overall smaller number of vector comparisons required to find the nearest neighbors. But at the same time require more time to build index.
Large segments benefit from the size of the index and overall smaller number of vector comparisons required to find the nearest neighbors. But at the same time require more time to build index.
```http
@@ -302,14 +295,13 @@ client.recreate_collection(
)
```
## Serve vectors for many independent users
This is a common use case when you want to provide vector search for multiple independent partitions.
These partitions may be divided by users, organizations, or other criteria.
However, for simplicity, we will refer to them as users.
Each user should have access only to their own vectors and should not be able to view vectors of other users.
Each user should have only access to their own vectors and should not be able to view the vectors of other users.
There are several ways to achieve this in Qdrant:
@@ -409,7 +401,6 @@ client.search(
)
```
However, the speed of indexation may become a bottleneck in this case, as each user's vector will be indexed into the same collection. To avoid this bottleneck, consider _bypassing the construction of a global vector index_ for the entire collection and building it only for individual groups instead.
By adopting this strategy, Qdrant will index vectors for each user independently, significantly accelerating the process.
@@ -471,22 +462,21 @@ client.create_payload_index(
)
```
## Bulk upload a large number of vectors
Uploading a large-scale dataset fast might be a challenge, but Qdrant has a few tricks to help you with that.
First important detail about data uploading is that the bottleneck is usually located on the client side, not on the server side.
The first important detail about data uploading is that the bottleneck is usually located on the client side, not on the server side.
This means that if you are uploading a large dataset, you should prefer a high-performance client library.
We recommend using [Rust client library](https://github.com/qdrant/rust-client) for this purpose, as it is the fastest client library available for Qdrant.
We recommend using our [Rust client library](https://github.com/qdrant/rust-client) for this purpose, as it is the fastest client library available for Qdrant.
If you are not using Rust, you might want to consider parallelizing your upload process.
### Disable indexing during upload
In case you are doing an initial upload of a large dataset, you might want to disable indexing during upload.
It will allow to avoid unnecessary indexing of vectors, which will be overwritten by the next batch.
It will enable to avoid unnecessary indexing of vectors, which will be overwritten by the next batch.
To disable indexing during upload, set `indexing_threshold` to some large value, like `1000000000`:
@@ -520,7 +510,7 @@ client.recreate_collection(
### Parallel upload into multiple shards
In Qdrant, each collection is split into shards. Each shard is a separate Write-Ahead-Log (WAL), which is responsible for ordering operations.
In Qdrant, each collection is split into shards. Each shard has a separate Write-Ahead-Log (WAL), which is responsible for ordering operations.
By creating multiple shards, you can parallelize upload of a large dataset. From 2 to 4 shards per one machine is a reasonable number.
```http
@@ -549,12 +539,12 @@ client.recreate_collection(
## Choose optimizer parameters
Optimizer is a fundamental architecture component of Qdrant.
The optimizer is a fundamental architecture component of Qdrant.
It is responsible for indexing, merging, vacuuming, and quantizing segments of the collection.
Optimizer allows to combine dynamic updates of any record in the collection with the ability to perform efficient bulk updates. It is especially important for building efficient indexes, which require knowledge of various statistics and distributions before they can be built.
The optimizer allows to combine dynamic updates of any record in the collection with the ability to perform efficient bulk updates. It is especially important for building efficient indexes, which require knowledge of various statistics and distributions before they can be built.
The parameters, which affect optimizer behavior the most are:
The parameters which affect the most the optimizer's behavior are:
```yaml
# Target amount of segments optimizer will try to keep.
@@ -593,13 +583,13 @@ indexing_threshold_kb: 20000
Those parameters are working as a conditional statement, which is evaluated for each segment after each update.
If the condition is true, the segment will be scheduled for optimization.
Values of those parameters will affect how qdrant handles updates of the data.
The values of those parameters will affect how Qdrant handles updates of the data.
- If you have enough RAM and CPU, it fine to go with default values - qdrant will index all vectors as fast as possible.
- If you have a limited amount of RAM, you can set `memmap_threshold_kb=20000` same value as `indexing_threshold_kb`. It will ensure that all vectors will be stored on disk as the same optimization iteration as indexation.
- If you have enough RAM and CPU, it is fine to go with default values - Qdrant will index all vectors as fast as possible.
- If you have a limited amount of RAM, you can set `memmap_threshold_kb=20000` to the same value as `indexing_threshold_kb`. This ensures that all vectors will be stored on disk during the optimization iteration running the indexation.
- If you are doing bulk updates, you can set `indexing_threshold_kb=100000000` (some very large value) to **disable** indexing during bulk updates. It will speed up the process significantly, but will require additional parameter change after bulk updates are finished.
Depending on your collection, you might have not enough vectors per segment to start building index.
Depending on your collection, you might not have enough vectors per segment to start building the index.
E.g. if you have 100k vecotrs and 8 segments, one for each CPU core, each segment will have only 12.5k vectors, which is not enough to build index.
In this case, you can set `indexing_threshold_kb=5000` to start building index even for small segments.
@@ -56,7 +56,7 @@ If you are applying Qdrant for the first time or working on a prototype, you mig
Qdrant provides a set of clients for different programming languages. You can find them here:
* [Python](https://github.com/qdrant/qdrant_client) - `pip install qdrant-client`
* [Python](https://github.com/qdrant/qdrant-client) - `pip install qdrant-client`
* [Rust](https://github.com/qdrant/rust-client) - `cargo add qdrant-client`
* [Go](https://github.com/qdrant/go-client) - `go get github.com/qdrant/go-client`
@@ -43,7 +43,6 @@ There are two ways to do this:
1. You can set the threshold globally in the [configuration file](../configuration/). The parameter is called `memmap_threshold_kb`.
2. You can set the threshold for each collection separately during [creation](../collections/#create-collection) or [update](../collections/#update-collection-parameters).
```http
PUT /collections/{collection_name}
@@ -70,15 +69,14 @@ client.recreate_collection(
)
```
The rule of thumb is to set the mmap threshold parameter is simple:
- if you have balanced use scenario - set mmap threshold same as `indexing_threshold` (default is 20000). In this case optimizer will not make extra runs and optimize all thresholds at once.
- if you have a high write load and low RAM - set mmap threshold lower than `indexing_threshold` to e.g. 10000. In this case optimizer will convert segments to mmap storage first and will only apply indexing after that.
The rule of thumb to set the mmap threshold parameter is simple:
- if you have a balanced use scenario - set mmap threshold the same as `indexing_threshold` (default is 20000). In this case the optimizer will not make any extra runs and will optimize all thresholds at once.
- if you have a high write load and low RAM - set mmap threshold lower than `indexing_threshold` to e.g. 10000. In this case the optimizer will convert the segments to mmap storage first and will only apply indexing after that.
In addition, you can use mmap storage not only for vectors, but also for HNSW index.
To enable this, you need to set the `hnsw_config.on_disk` parameter to `true` during [creation](../collections/#create-collection) of the collection.
```http
PUT /collections/{collection_name}
@@ -109,13 +107,12 @@ client.recreate_collection(
)
```
## Payload storage
Qdrant supports two types of payload storages: InMemory and OnDisk.
InMemory payload storage is organized in the same way as in-memory vectors.
Payload is loaded into RAM at service startup while disk and [RocksDB](https://rocksdb.org/) are used for persistence only.
The payload data is loaded into RAM at service startup while disk and [RocksDB](https://rocksdb.org/) are used for persistence only.
This type of storage works quite fast, but it may require a lot of space to keep all the data in RAM, especially if the payload has large values attached - abstracts of text or even images.
In the case of large payload values, it might be better to use OnDisk payload storage.
@@ -132,8 +129,8 @@ You can specify the desired type of payload storage with [configuration file](..
To ensure data integrity, Qdrant performs all data changes in 2 stages.
In the first step, the data is written to the Write-ahead-log(WAL), which orders all operations and assigns them a sequential number.
Once a change has been added to the WAL, it will not be lost even if power loss occurs.
Once a change has been added to the WAL, it will not be lost even if a power loss occurs.
Then the changes go into the segments.
Each segment stores the last version of the change applied to it as well as version of each individual point.
Each segment stores the last version of the change applied to it as well as the version of each individual point.
If the new change has a sequential number less than the current version of the point, the updater will ignore the change.
This mechanism allows Qdrant to safely and efficiently restore the storage from the WAL in case of an abnormal shutdown.
@@ -8,4 +8,4 @@ sitemapExclude: True
---
Provides the [OpenAPI v3 specification](https://qdrant.github.io/qdrant/redoc/index.html) to generate a client library in almost any programming language.
Alternatively utilise [ready-made client for Python](https://github.com/qdrant/qdrant_client) or other programming languages with additional functionality.
Alternatively utilise [ready-made client for Python](https://github.com/qdrant/qdrant-client) or other programming languages with additional functionality.