> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# layout de dictionnaire cache

> Stocke un dictionnaire dans un cache en mémoire de taille fixe.

Le type de layout de dictionnaire `cached` stocke le dictionnaire dans un cache comportant un nombre fixe de cellules.
Ces cellules contiennent des éléments fréquemment utilisés.

La clé du dictionnaire est de type [UInt64](/fr/reference/data-types/int-uint).

Lors d'une recherche dans un dictionnaire, le cache est consulté en premier. Pour chaque bloc de données, toutes les clés qui ne sont pas trouvées dans le cache ou qui sont obsolètes sont demandées à la source à l'aide de `SELECT attrs... FROM db.table WHERE id IN (k1, k2, ...)`. Les données reçues sont ensuite écrites dans le cache.

Cela s'applique à la **recherche** d'une clé — `dictGet` et les autres fonctions de dictionnaire. Lire le dictionnaire **en tant que table** avec `SELECT ... FROM <dictionary>` est différent : comme un cache ne conserve aucune trace des clés existantes, la lecture énumère uniquement les cellules qui se trouvent présentes dans le cache à cet instant et qui contiennent une valeur, et un `WHERE` sur la clé est un filtre ordinaire appliqué à ces cellules, et non une liste de clés à récupérer. Une clé absente du cache ne peut pas être découverte de cette manière, quel que soit le contenu du `WHERE`. Une clé qui *a* été recherchée mais qui n'a pas été trouvée à la source n'est pas visible non plus : le cache mémorise l'échec sous la forme d'une cellule par défaut, et une lecture sous forme de table ignore les cellules par défaut. Les cellules présentes ne sont pas non plus exemptes de sollicitation de la source : une cellule expirée est lue via le même chemin que `dictGet`, elle est donc redemandée à la source — de manière synchrone, ou asynchrone si `allow_read_expired_keys` est activé.

```sql theme={null}
CREATE DICTIONARY cache_dict (id UInt64, data String) PRIMARY KEY id
SOURCE(CLICKHOUSE(TABLE 'cache_src')) LIFETIME(MIN 0 MAX 900) LAYOUT(CACHE(SIZE_IN_CELLS 1000));

-- nothing is cached yet, so nothing comes back and the source is not queried
SELECT count() FROM cache_dict WHERE id IN (1, 2, 3);
0

-- looking the keys up populates the cache
SELECT dictGet('cache_dict', 'data', toUInt64(number + 1)) FROM numbers(3);

-- and now the same read sees them
SELECT count() FROM cache_dict WHERE id IN (1, 2, 3);
3
```

Un dictionnaire cache doit donc être utilisé via les fonctions de dictionnaire. Si vous avez besoin qu'une recherche de clés arbitraires atteigne toujours la source, utilisez `dictGet` avec le layout [direct](/fr/reference/statements/create/dictionary/layouts/direct), qui interroge la source à chaque recherche et ne met rien en cache. Notez qu'une lecture sous forme de table d'un dictionnaire `direct` n'est pas non plus une récupération par clé : `SELECT ... FROM <dictionary> WHERE key IN (...)` charge l'intégralité de la source puis applique le filtre, car ClickHouse ne pousse pas le filtre sur la clé dans le dictionnaire. Pour lire un dictionnaire sous forme de table, utilisez un layout qui le contient entièrement, tel que [flat](/fr/reference/statements/create/dictionary/layouts/flat) ou [hashed](/fr/reference/statements/create/dictionary/layouts/hashed).

Si des clés ne sont pas trouvées dans le dictionnaire, une tâche de mise à jour du cache est créée et ajoutée à la file d'attente de mise à jour. Les propriétés de cette file d'attente peuvent être contrôlées avec les paramètres `max_update_queue_size`, `update_queue_push_timeout_milliseconds`, `query_wait_timeout_milliseconds`, `max_threads_for_updates`.

Pour les dictionnaires cache, la [durée de vie](/fr/reference/statements/create/dictionary/lifetime) des données dans le cache peut être définie. Si un délai supérieur à `lifetime` s'est écoulé depuis le chargement des données dans une cellule, la valeur de la cellule n'est pas utilisée et la clé expire. La clé est redemandée la prochaine fois qu'elle doit être utilisée. Ce comportement peut être configuré avec le paramètre `allow_read_expired_keys`.

C'est la méthode la moins efficace de toutes pour stocker des dictionnaires. La vitesse du cache dépend fortement du bon réglage des paramètres et du scénario d'utilisation. Un dictionnaire de type cache n'est performant que lorsque le taux de réussite est suffisamment élevé (99 % ou plus recommandé). Vous pouvez consulter le taux de réussite moyen dans la table [system.dictionaries](/fr/reference/system-tables/dictionaries).

Si le paramètre `allow_read_expired_keys` est défini sur 1 (0 par défaut), le dictionnaire peut alors prendre en charge des mises à jour asynchrones. Si un client demande des clés et qu'elles sont toutes dans le cache, mais que certaines ont expiré, le dictionnaire renverra au client les clés expirées et les redemandera de manière asynchrone à la source.

Pour améliorer les performances du cache, utilisez une sous-requête avec `LIMIT` et appelez la fonction avec le dictionnaire à l'extérieur.

Tous les types de sources sont pris en charge.

Exemple de paramètres :

<Tabs>
  <Tab title="DDL">
    ```sql theme={null}
    LAYOUT(CACHE(SIZE_IN_CELLS 1000000000))
    ```
  </Tab>

  <Tab title="Fichier de configuration">
    ```xml theme={null}
    <layout>
        <cache>
            <!-- La taille du cache, en nombre de cellules. Arrondie à une puissance de deux. -->
            <size_in_cells>1000000000</size_in_cells>
            <!-- Permet de lire les clés expirées. -->
            <allow_read_expired_keys>0</allow_read_expired_keys>
            <!-- Taille maximale de la file d'attente de mise à jour. -->
            <max_update_queue_size>100000</max_update_queue_size>
            <!-- Délai d'attente maximal, en millisecondes, pour ajouter une tâche de mise à jour à la file d'attente. -->
            <update_queue_push_timeout_milliseconds>10</update_queue_push_timeout_milliseconds>
            <!-- Délai d'attente maximal, en millisecondes, pour que la tâche de mise à jour se termine. -->
            <query_wait_timeout_milliseconds>60000</query_wait_timeout_milliseconds>
            <!-- Nombre maximal de threads pour la mise à jour du dictionnaire cache. -->
            <max_threads_for_updates>4</max_threads_for_updates>
        </cache>
    </layout>
    ```
  </Tab>
</Tabs>

<br />

Définissez une taille de cache suffisamment grande. Vous devrez faire des essais pour choisir le nombre de cellules :

1. Définissez une valeur.
2. Exécutez des requêtes jusqu'à ce que le cache soit complètement rempli.
3. Évaluez la consommation de mémoire à l'aide de la table `system.dictionaries`.
4. Augmentez ou diminuez le nombre de cellules jusqu'à atteindre la consommation mémoire souhaitée.

<Note>
  ClickHouse n'est pas recommandé comme source pour ce layout. Les recherches dans le dictionnaire nécessitent des lectures ponctuelles aléatoires, ce qui ne correspond pas au modèle d'accès pour lequel ClickHouse est optimisé.
</Note>
