Chaque collection de données est divisée en segments. Chaque segment a un stockage vectoriel indépendant, un stockage de payload et un index.

Les données dans les segments ne se chevauchent généralement pas. Cependant, le stockage du même point dans différents segments ne pose pas de problèmes car la recherche contient un mécanisme de déduplication.

Les segments comprennent un stockage vectoriel, un stockage de payload, un index vectoriel, un index de payload et un mappage d'ID pour stocker la relation entre les ID internes et externes.

Les segments peuvent être "ajoutables" ou "non-ajoutables" en fonction du type de stockage et de l'index utilisé. Vous pouvez librement ajouter, supprimer et interroger des données dans les segments "ajoutables", tandis que les segments "non-ajoutables" ne peuvent que lire et supprimer des données.

La configuration des segments dans une collection peut être différente et indépendante les unes des autres, mais au moins un segment "ajoutable" est requis.

Stockage Vectoriel

En fonction des besoins de l'application, Qdrant peut utiliser l'une des options de stockage de données suivantes. Le choix doit trouver un équilibre entre la vitesse de recherche et l'utilisation de la RAM.

Stockage en Mémoire - Stocke tous les vecteurs en RAM, offrant la vitesse la plus élevée car l'accès au disque n'est requis que lors de la persistance.

Stockage Memmap - Crée un espace d'adressage virtuel associé à un fichier sur le disque. Les fichiers mappés ne sont pas directement chargés en RAM mais sont accessibles à l'aide d'une mise en cache par pages. Cette approche permet une utilisation flexible de la mémoire disponible. Avec suffisamment de RAM, sa vitesse est presque aussi rapide que le stockage en mémoire.

Configuration du Stockage Memmap

Il existe deux façons de configurer l'utilisation de memmap (également appelé stockage sur disque) :

  • Définir l'option on_disk pour les vecteurs dans l'API de création de collection :

Applicable uniquement à partir de la version v1.2.0

PUT /collections/{collection_name}

{
    "vectors": {
      "size": 768,
      "distance": "Cosine",
      "on_disk": true
    }
}

Cela créera une collection qui stocke immédiatement tous les vecteurs dans le stockage memmap. C'est l'approche recommandée lorsque l'instance de Qdrant utilise des disques rapides et doit gérer de grandes collections.

  • Définir l'option memmap_threshold_kb. Cette option définit le seuil de conversion des segments en stockage memmap.

Il existe deux façons de mettre en œuvre cela :

  1. Définir le seuil globalement dans le fichier de configuration. Le nom du paramètre est memmap_threshold_kb.
  2. Définir le seuil individuellement pour chaque collection lors de la création ou de la mise à jour.
PUT /collections/{collection_name}

{
    "vectors": {
      "size": 768,
      "distance": "Cosine"
    },
    "optimizers_config": {
        "memmap_threshold": 20000
    }
}

La règle générale pour définir le paramètre de seuil memmap est simple :

  • Si le scénario d'utilisation est équilibré - définissez le seuil memmap de la même manière que le indexing_threshold (par défaut à 20000). Dans ce cas, l'optimiseur ne réalisera pas d'exécutions supplémentaires et optimisera tous les seuils en une seule fois.
  • Si la charge d'écriture est élevée et que la RAM est faible - définissez le seuil memmap inférieur au indexing_threshold, par exemple 10000. Dans ce cas, l'optimiseur convertira d'abord les segments en stockage memmap, puis appliquera l'indexation.

De plus, vous pouvez utiliser le stockage memmap non seulement pour les vecteurs, mais aussi pour les index HNSW. Pour activer cette fonctionnalité, définissez le paramètre hnsw_config.on_disk sur true lors de la création de la collection.

PUT /collections/{collection_name}

{
    "vectors": {
      "size": 768,
      "distance": "Cosine"
    },
    "optimizers_config": {
        "memmap_threshold": 20000
    },
    "hnsw_config": {
        "on_disk": true
    }
}

Stockage des données

Qdrant prend en charge deux types de stockage des données : en mémoire et sur disque.

Le stockage des données en mémoire organise les données de charge utile de la même manière que les vecteurs en mémoire. Les données de charge utile sont chargées en mémoire au démarrage du service, tandis que le disque et RocksDB sont utilisés uniquement pour la persistance. Ce type de stockage est très rapide, mais peut nécessiter une grande quantité d'espace mémoire pour stocker toutes les données, en particulier si la charge utile inclut de grandes valeurs (telles que des résumés textuels ou même des images).

Pour les valeurs de charge utile importantes, il est préférable d'utiliser le stockage des données sur disque. Ce type de stockage lit et écrit directement la charge utile dans RocksDB, ne nécessitant ainsi pas une grande quantité de mémoire pour le stockage. Cependant, l'inconvénient est la latence d'accès. Si vous avez besoin d'interroger des vecteurs en fonction de conditions de charge utile, la vérification des valeurs stockées sur disque peut prendre trop de temps. Dans ce cas, nous recommandons de créer un index de charge utile pour chaque champ utilisé pour les conditions de filtrage afin d'éviter l'accès au disque. Une fois l'index de champ créé, Qdrant conservera toujours toutes les valeurs du champ indexé en mémoire, quel que soit le type de stockage de la charge utile.

Vous pouvez spécifier le type de stockage de la charge utile souhaité via le fichier de configuration ou en utilisant le paramètre de collection on_disk_payload lors de la création d'une collection.

Contrôle de version

Pour garantir l'intégrité des données, Qdrant effectue toutes les modifications de données en deux étapes. Tout d'abord, les données sont écrites dans le journal d'écriture différée (WAL), qui trie et attribue des numéros séquentiels à toutes les opérations.

Une fois que les modifications sont ajoutées au WAL, elles ne sont pas perdues même en cas de panne de courant. Ensuite, les modifications entrent dans le segment. Chaque segment stocke la dernière version des modifications qui lui sont appliquées, ainsi que la version de chaque point individuel. Si le numéro séquentiel d'une nouvelle modification est inférieur à la version actuelle d'un point, le programme de mise à jour ignorera cette modification. Ce mécanisme permet à Qdrant de récupérer efficacement le stockage à partir du WAL en cas d'arrêts anormaux.