> ## 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.

> Utilisation avancée avec ClickHouse Connect

# Utilisation avancée

<h2 id="raw-api">
  API brute
</h2>

Pour les cas d’utilisation ne nécessitant pas de transformation entre les données ClickHouse et des types ou structures de données natifs ou tiers, le client ClickHouse Connect fournit des méthodes permettant d’utiliser directement la connexion ClickHouse.

<h3 id="client-rawquery-method">
  Méthode `raw_query` de `Client`
</h3>

La méthode `Client.raw_query` permet d'utiliser directement l'interface de requête HTTP de ClickHouse via la connexion du client. La valeur de retour est un objet `bytes` non traité. Elle fournit un wrapper pratique avec liaison de paramètres, gestion des erreurs, réessais et gestion des paramètres via une interface minimale :

| Paramètre | Type | Par défaut | Description |
| - | - | - | - |
| `query` | str | Obligatoire | Toute requête ClickHouse valide. |
| `parameters` | dict or sequence | `None` | Voir la [description des paramètres](/fr/integrations/language-clients/python/driver-api#parameters-argument). |
| `settings` | dict | `None` | Voir l’[argument Settings](/fr/integrations/language-clients/python/driver-api#settings-argument-1). |
| `fmt` | str | `None` | Format de sortie ClickHouse pour les octets renvoyés. (ClickHouse utilise TSV s'il n'est pas spécifié) |
| `use_database` | bool | `True` | Inclure la base de données configurée sur le client. |
| `external_data` | `ExternalData` | `None` | Fichier externe ou données binaires. Voir [Données externes](/fr/integrations/language-clients/python/advanced-querying#external-data). |
| `transport_settings` | dict | `None` | En-têtes HTTP ajoutés à cette requête. |

Il incombe à l'appelant de traiter l'objet `bytes` renvoyé. Notez que `Client.query_arrow` n'est qu'un simple wrapper de cette méthode utilisant le format de sortie ClickHouse `Arrow`.

<h3 id="client-rawstream-method">
  Méthode `raw_stream` de `Client`
</h3>

La méthode synchrone `Client.raw_stream` a la même API que `raw_query`, mais renvoie un flux `io.IOBase` de fragments d’octets. Fermez le flux une fois le traitement terminé. `AsyncClient.raw_stream` s’utilise avec `await` et renvoie un `StreamContext` asynchrone à utiliser avec `async with` et `async for`.

<h3 id="client-rawinsert-method">
  Méthode `raw_insert` de `Client`
</h3>

La méthode `Client.raw_insert` permet d’effectuer des insertions directes d’objets `bytes` ou de générateurs d’objets `bytes` via la connexion du client. Comme elle n’effectue aucun traitement de la charge utile d’insertion, elle est très performante. La méthode propose des options pour spécifier les settings et le format d’insertion :

| Paramètre | Type | Par défaut | Description |
| - | - | - | - |
| `table` | str | Obligatoire | Table cible simple ou qualifiée par la base de données. |
| `column_names` | Sequence\[str] | `None` | Noms des colonnes pour le bloc d’insertion. Obligatoire lorsque `fmt` n’inclut pas de noms. |
| `insert_block` | str, bytes, generator, or `BinaryIO` | Obligatoire | Données à insérer. Les chaînes sont encodées avec l’encodage du client. |
| `settings` | dict | `None` | Voir [l’argument Settings](/fr/integrations/language-clients/python/driver-api#settings-argument-1). |
| `fmt` | str | `None` | Format d’entrée ClickHouse de la charge utile `insert_block`. `Native` est utilisé lorsqu’aucun format n’est spécifié. |
| `compression` | str | `None` | Compression déjà appliquée à `insert_block`, comme `"gzip"`, `"lz4"` ou `"zstd"`. |
| `transport_settings` | dict | `None` | En-têtes HTTP ajoutés à cette requête. |

Il incombe à l’appelant de s’assurer que `insert_block` est dans le format spécifié et utilise la méthode de compression spécifiée. ClickHouse Connect utilise ces insertions brutes pour les téléversements de fichiers et les tables PyArrow, en déléguant le parsing au serveur ClickHouse.

<h2 id="saving-query-results-as-files">
  Enregistrer les résultats d’une requête dans des fichiers
</h2>

Vous pouvez diffuser des fichiers directement de ClickHouse vers le système de fichiers local à l’aide de la méthode `raw_stream`. Par exemple, si vous souhaitez enregistrer le résultat d’une requête dans un fichier CSV, vous pouvez utiliser l’extrait de code suivant :

```python theme={null}
import clickhouse_connect

if __name__ == "__main__":
    client = clickhouse_connect.get_client()
    query = (
        "SELECT number, toString(number) AS number_as_str "
        "FROM system.numbers LIMIT 5"
    )
    stream = client.raw_stream(query=query, fmt="CSVWithNames")
    try:
        with open("output.csv", "wb") as file:
            for chunk in stream:
                file.write(chunk)
    finally:
        stream.close()
        client.close()
```

Le code ci-dessus génère un fichier `output.csv` avec le contenu suivant :

```csv theme={null}
"number","number_as_str"
0,"0"
1,"1"
2,"2"
3,"3"
4,"4"
```

De même, vous pouvez enregistrer les données au format [TabSeparated](/fr/reference/formats/TabSeparated/TabSeparated), ainsi que dans d'autres formats. Consultez [Formats des données d'entrée et de sortie](/fr/reference/formats) pour obtenir un aperçu de toutes les options de format disponibles.

<h2 id="multithreaded-multiprocess-and-asyncevent-driven-use-cases">
  Cas d'utilisation multithread, multiprocessus et asynchrones/pilotés par événements
</h2>

ClickHouse Connect fonctionne bien dans les applications multithread, multiprocessus et pilotées par une boucle d'événements/asynchrones. Tout le traitement des requêtes et des insertions s'effectue dans un seul thread, de sorte que les opérations sont généralement thread-safe. (Le traitement parallèle de certaines opérations à bas niveau pourrait être ajouté ultérieurement pour compenser la pénalité de performances liée à l'utilisation d'un seul thread, mais même dans ce cas, la thread safety sera préservée.)

Comme chaque requête ou insertion exécutée conserve son état dans son propre objet `QueryContext` ou `InsertContext`, respectivement, ces objets utilitaires ne sont pas thread-safe et ne doivent pas être partagés entre plusieurs flux de traitement. Consultez également les explications supplémentaires sur les objets de contexte dans les sections [QueryContexts](/fr/integrations/language-clients/python/advanced-querying#querycontexts) et [InsertContexts](/fr/integrations/language-clients/python/advanced-inserting#insertcontexts).

De plus, dans une application où deux requêtes et/ou insertions ou plus sont « en cours » au même moment, il faut garder à l'esprit deux autres points. Le premier concerne la « session » ClickHouse associée à la requête/insertion, et le second le pool de connexions HTTP utilisé par les instances de ClickHouse Connect Client.

<h2 id="asyncclient">
  AsyncClient
</h2>

ClickHouse Connect fournit un client natif reposant sur aiohttp pour les applications asyncio. Installez la dépendance facultative avant de l’utiliser :

```bash theme={null}
pip install "clickhouse-connect[async]"
```

Utilisez `await` avec `get_async_client` pour créer et initialiser un client. Les méthodes d’E/S telles que `query`, `command` et `insert` sont des coroutines :

```python theme={null}
import asyncio

import clickhouse_connect


async def main():
    async with await clickhouse_connect.get_async_client() as client:
        result = await client.query(
            "SELECT name FROM system.databases ORDER BY name LIMIT 1"
        )
        print(result.result_rows)


asyncio.run(main())
```

Le client asynchrone suit le même contrat de requête, d’insertion, raw, Arrow et de streaming que le client synchrone. Il utilise aiohttp pour les E/S réseau. Le parsing du format Native, gourmand en CPU, peut s’exécuter dans un executor afin de ne pas bloquer la boucle d’événements.

Un client asynchrone possède une session aiohttp créée dans une boucle d’événements donnée. Avant de déplacer le client vers une autre boucle d’événements, fermez-le dans la boucle à laquelle il appartient, puis appelez `await client._initialize()` dans la nouvelle boucle avant d’envoyer des requêtes. Si cette boucle d’origine est déjà fermée, appelez `await client.close()` puis `await client._initialize()` dans la boucle courante. aiohttp peut encore signaler un transport non fermé si le nettoyage ne commence qu’après la fermeture de la boucle d’origine ; dans la mesure du possible, fermez donc le client avant de le transférer.

Les méthodes de streaming asynchrones doivent être attendues avant d’entrer dans le contexte renvoyé :

```python theme={null}
async with await client.query_rows_stream(
    "SELECT number FROM numbers(100000)"
) as stream:
    async for row in stream:
        process(row)
```

Contrairement à la fabrique synchrone, `get_async_client` désactive par défaut la génération automatique des ID de session afin que plusieurs coroutines concurrentes puissent partager un client. Ne fournissez un `session_id` explicite ou `autogenerate_session_id=True` que si vous avez besoin de l’état de session et pouvez garantir l’absence de requêtes concurrentes dans cette session.

<h2 id="managing-clickhouse-session-ids">
  Gestion des ID de session ClickHouse
</h2>

Chaque requête ClickHouse s’exécute dans le contexte d’une « session » ClickHouse. Les sessions sont actuellement utilisées à deux fins :

* Associer des paramètres ClickHouse spécifiques à plusieurs requêtes (voir les [paramètres utilisateur](/fr/reference/settings/session-settings)). La commande ClickHouse `SET` est utilisée pour modifier les paramètres dans le cadre d’une session utilisateur.
* Suivre les [tables temporaires.](/fr/reference/statements/create/table#temporary-tables)

Par défaut, un `Client` synchrone utilise un ID de session généré. Les instructions `SET` et les tables temporaires ne sont conservées d’une requête à l’autre pour ce client que si ces requêtes aboutissent au même processus serveur ClickHouse. La fabrique async ne génère pas d’ID de session par défaut. L’état des sessions nommées et les vérifications de chevauchement au sein d’une même session sont locaux au processus, et le client lève une `ProgrammingError` lorsqu’il détecte un chevauchement local avant d’envoyer la requête. Dans ClickHouse Cloud ou dans d’autres déploiements avec répartition de charge, ne vous appuyez pas sur un `session_id` fixe comme état distribué ni comme mutex distribué. Si le chevauchement pose problème, sérialisez les requêtes avant de les envoyer à ClickHouse. Utilisez l’une des approches suivantes :

1. Créez une instance `Client` distincte pour chaque thread/process/event handler nécessitant une isolation de session. Cela préserve l’état de session propre à chaque client (tables temporaires et valeurs `SET`).
2. Utilisez un `session_id` unique pour chaque requête via l’argument `settings` lors de l’appel à `query`, `command` ou `insert`, si vous n’avez pas besoin d’un état de session partagé.
3. Désactivez les sessions sur un client partagé en définissant `autogenerate_session_id=False` avant de créer le client (ou transmettez-le directement à `get_client`).

```python theme={null}
import clickhouse_connect
from clickhouse_connect import common

common.set_setting("autogenerate_session_id", False)
client = clickhouse_connect.get_client(
    host="somehost.com",
    username="dbuser",
    password="password",
)
```

Vous pouvez aussi passer `autogenerate_session_id=False` directement à `get_client(...)`.

Dans ce cas, ClickHouse Connect n'envoie pas de `session_id` ; le serveur ne considère pas les requêtes distinctes comme appartenant à la même session. Les tables temporaires et les paramètres de session ne seront pas conservés d'une requête à l'autre.

<h2 id="customizing-the-http-connection-pool">
  Personnalisation du pool de connexions HTTP
</h2>

ClickHouse Connect utilise les pools de connexions `urllib3` pour gérer la connexion HTTP sous-jacente avec le serveur. Par défaut, toutes les instances client synchrones d’un même processus partagent le même pool de connexions, ce qui suffit dans la plupart des cas d’usage. Chaque worker de multiprocessing dispose de son propre pool par défaut, local au processus, qu’il réutilise pour tous les clients créés en son sein. Un client créé avant un fork conserve le pool du processus parent et ne doit pas être utilisé dans le processus enfant. Le pool par défaut gère jusqu’à 8 connexions HTTP Keep Alive vers chaque serveur ClickHouse utilisé par l’application.

Les options de socket par défaut activent le keepalive TCP et `TCP_NODELAY`. La taille des tampons d’envoi et de réception des sockets est gérée par le système d’exploitation.

Pour les applications multithreadées de grande taille, il peut être préférable d’utiliser des pools de connexions distincts. Des pools de connexions personnalisés peuvent être fournis via l’argument nommé `pool_mgr` de la fonction principale `clickhouse_connect.get_client` :

```python theme={null}
import clickhouse_connect
from clickhouse_connect.driver import httputil

big_pool_mgr = httputil.get_pool_manager(maxsize=16, num_pools=12)

client1 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)
client2 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)
```

Les clients peuvent partager un même gestionnaire de pool, ou bien chaque client peut utiliser un gestionnaire distinct. Pour plus de détails, consultez la [documentation du `PoolManager` d’`urllib3`](https://urllib3.readthedocs.io/en/stable/advanced-usage.html#customizing-pool-behavior).

Pour définir des options de socket, passez `socket_options` à `httputil.get_pool_manager` ou à `httputil.get_pool_manager_options`. Cela remplace l’intégralité de la liste par défaut, y compris les options keepalive et `TCP_NODELAY`. Passez `[]` ou `None` pour n’appliquer aucune option de socket explicite.

Le client asynchrone utilise un pool `aiohttp` plutôt que `urllib3`. Configurez-le à l’aide de `connector_limit`, `connector_limit_per_host` et `keepalive_timeout` via `get_async_client`. L’appel à `await async_client.close_connections()` renouvelle le pool sans interrompre les requêtes en cours.

Pour les requêtes et insertions async, l’attente d’un slot libre dans le pool n’est soumise à aucun délai d’expiration. Lisez entièrement ou fermez les réponses en streaming afin de libérer leurs slots de pool. Le décompte de `connect_timeout` commence une fois qu’un slot est disponible et couvre la résolution DNS, l’établissement des connexions TCP et TLS, ainsi que la négociation avec le proxy. `send_receive_timeout` limite la durée des lectures sur le socket. Pour fixer une échéance à l’ensemble de l’opération, attente du pool comprise, utilisez `asyncio.wait_for`, par exemple `await asyncio.wait_for(client.query("SELECT 13"), timeout=30)`.
