> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# catalogue Lakekeeper

> Dans ce guide, nous vous montrons comment interroger vos données avec ClickHouse et le catalogue Lakekeeper.

export const ExperimentalBadge = () => {
  return <div className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Fonctionnalité expérimentale. <u><a href="/docs/docs/beta-and-experimental-features#experimental-features">En savoir plus.</a></u>
        </div>;
};

<ExperimentalBadge />

<Note>
  L’intégration avec le catalogue Lakekeeper fonctionne uniquement avec les tables Iceberg.
  Cette intégration prend en charge à la fois AWS S3 et d’autres fournisseurs de stockage cloud.
</Note>

ClickHouse prend en charge l’intégration avec plusieurs catalogues (Unity, Glue, REST, Polaris, etc.). Ce guide vous explique les étapes à suivre pour interroger vos données à l’aide de ClickHouse et du catalogue [Lakekeeper](https://docs.lakekeeper.io/).

Lakekeeper est une implémentation open source de REST catalog pour Apache Iceberg qui fournit :

* une implémentation **native en Rust** offrant de hautes performances et une grande fiabilité
* la conformité de l’**API REST** avec la spécification REST catalog d’Iceberg
* l’intégration au **stockage cloud** avec un stockage compatible S3

<Note>
  Cette fonctionnalité étant expérimentale, vous devrez l’activer avec :
  `SET allow_experimental_database_iceberg = 1;`
</Note>

<div id="local-development-setup">
  ## Configuration de développement en local
</div>

Pour le développement et les tests en local, vous pouvez utiliser une configuration Lakekeeper conteneurisée. Cette approche est idéale pour l’apprentissage, le prototypage et les environnements de développement.

<div id="local-prerequisites">
  ### Prérequis
</div>

1. **Docker et Docker Compose** : Assurez-vous que Docker est installé et en cours d’exécution
2. **Configuration d’exemple** : Vous pouvez utiliser la configuration Docker Compose de Lakekeeper

<div id="setting-up-local-lakekeeper-catalog">
  ### Configuration d’un catalogue Lakekeeper local
</div>

Vous pouvez utiliser la [configuration docker-compose officielle de Lakekeeper](https://github.com/lakekeeper/lakekeeper/tree/main/examples/minimal), qui fournit un environnement complet avec Lakekeeper, un backend PostgreSQL pour les métadonnées et MinIO pour le stockage objet.

**Étape 1 :** Créez un nouveau dossier dans lequel exécuter l’exemple, puis créez un fichier `docker-compose.yml` avec la configuration suivante :

```yaml theme={null}
version: '3.8'

services:
  lakekeeper:
    image: quay.io/lakekeeper/catalog:latest
    environment:
      - LAKEKEEPER__PG_ENCRYPTION_KEY=This-is-NOT-Secure!
      - LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://postgres:postgres@db:5432/postgres
      - LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://postgres:postgres@db:5432/postgres
      - RUST_LOG=info
    command: ["serve"]
    healthcheck:
      test: ["CMD", "/home/nonroot/lakekeeper", "healthcheck"]
      interval: 1s
      timeout: 10s
      retries: 10
      start_period: 30s
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy
      minio:
        condition: service_healthy
    ports:
      - 8181:8181
    networks:
      - iceberg_net

  migrate:
    image: quay.io/lakekeeper/catalog:latest-main
    environment:
      - LAKEKEEPER__PG_ENCRYPTION_KEY=This-is-NOT-Secure!
      - LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://postgres:postgres@db:5432/postgres
      - LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://postgres:postgres@db:5432/postgres
      - RUST_LOG=info
    restart: "no"
    command: ["migrate"]
    depends_on:
      db:
        condition: service_healthy
    networks:
      - iceberg_net

  bootstrap:
    image: curlimages/curl
    depends_on:
      lakekeeper:
        condition: service_healthy
    restart: "no"
    command:
      - -w
      - "%{http_code}"
      - "-X"
      - "POST"
      - "-v"
      - "http://lakekeeper:8181/management/v1/bootstrap"
      - "-H"
      - "Content-Type: application/json"
      - "--data"
      - '{"accept-terms-of-use": true}'
      - "-o"
      - "/dev/null"
    networks:
      - iceberg_net

  initialwarehouse:
    image: curlimages/curl
    depends_on:
      lakekeeper:
        condition: service_healthy
      bootstrap:
        condition: service_completed_successfully
    restart: "no"
    command:
      - -w
      - "%{http_code}"
      - "-X"
      - "POST"
      - "-v"
      - "http://lakekeeper:8181/management/v1/warehouse"
      - "-H"
      - "Content-Type: application/json"
      - "--data"
      - '{"warehouse-name": "demo", "project-id": "00000000-0000-0000-0000-000000000000", "storage-profile": {"type": "s3", "bucket": "warehouse-rest", "key-prefix": "", "assume-role-arn": null, "endpoint": "http://minio:9000", "region": "local-01", "path-style-access": true, "flavor": "minio", "sts-enabled": true}, "storage-credential": {"type": "s3", "credential-type": "access-key", "aws-access-key-id": "minio", "aws-secret-access-key": "ClickHouse_Minio_P@ssw0rd"}}'
      - "-o"
      - "/dev/null"
    networks:
      - iceberg_net

  db:
    image: bitnami/postgresql:16.3.0
    environment:
      - POSTGRESQL_USERNAME=postgres
      - POSTGRESQL_PASSWORD=postgres
      - POSTGRESQL_DATABASE=postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -p 5432 -d postgres"]
      interval: 2s
      timeout: 10s
      retries: 5
      start_period: 10s
    volumes:
      - postgres_data:/bitnami/postgresql
    networks:
      - iceberg_net

  minio:
    image: bitnami/minio:2025.4.22
    environment:
      - MINIO_ROOT_USER=minio
      - MINIO_ROOT_PASSWORD=ClickHouse_Minio_P@ssw0rd
      - MINIO_API_PORT_NUMBER=9000
      - MINIO_CONSOLE_PORT_NUMBER=9001
      - MINIO_SCHEME=http
      - MINIO_DEFAULT_BUCKETS=warehouse-rest
    networks: 
      iceberg_net:
        aliases:
          - warehouse-rest.minio
    ports:
      - "9002:9000"
      - "9003:9001"
    healthcheck:
      test: ["CMD", "mc", "ls", "local", "|", "grep", "warehouse-rest"]
      interval: 2s
      timeout: 10s
      retries: 3
      start_period: 15s
    volumes:
      - minio_data:/bitnami/minio/data

  clickhouse:
    image: clickhouse/clickhouse-server:head
    container_name: lakekeeper-clickhouse
    user: '0:0'  # Ensures root permissions
    ports:
      - "8123:8123"
      - "9000:9000"
    volumes:
      - clickhouse_data:/var/lib/clickhouse
      - ./clickhouse/data_import:/var/lib/clickhouse/data_import  # Mount dataset folder
    networks:
      - iceberg_net
    environment:
      - CLICKHOUSE_DB=default
      - CLICKHOUSE_USER=default
      - CLICKHOUSE_DO_NOT_CHOWN=1
      - CLICKHOUSE_PASSWORD=
    depends_on:
      lakekeeper:
        condition: service_healthy
      minio:
        condition: service_healthy

volumes:
  postgres_data:
  minio_data:
  clickhouse_data:

networks:
  iceberg_net:
    driver: bridge
```

**Étape 2 :** Exécutez la commande suivante pour démarrer les services :

```bash theme={null}
docker compose up -d
```

**Étape 3 :** Attendez que tous les services soient prêts. Vous pouvez consulter les logs :

```bash theme={null}
docker-compose logs -f
```

<Note>
  La configuration de Lakekeeper nécessite que les données d’exemple soient d’abord chargées dans les tables Iceberg. Assurez-vous que l’environnement a bien créé et alimenté les tables avant d’essayer de les interroger via ClickHouse. La disponibilité des tables dépend de la configuration `docker-compose` utilisée ainsi que des scripts de chargement des données d’exemple.
</Note>

<div id="connecting-to-local-lakekeeper-catalog">
  ### Se connecter au catalogue Lakekeeper local
</div>

Connectez-vous à votre conteneur ClickHouse :

```bash theme={null}
docker exec -it lakekeeper-clickhouse clickhouse-client
```

Créez ensuite la connexion de base de données au catalogue Lakekeeper :

```sql theme={null}
SET allow_experimental_database_iceberg = 1;

CREATE DATABASE demo
ENGINE = DataLakeCatalog('http://lakekeeper:8181/catalog', 'minio', 'ClickHouse_Minio_P@ssw0rd')
SETTINGS catalog_type = 'rest', storage_endpoint = 'http://minio:9002/warehouse-rest', warehouse = 'demo'
```

<div id="querying-lakekeeper-catalog-tables-using-clickhouse">
  ## Interroger les tables du catalogue Lakekeeper avec ClickHouse
</div>

Maintenant que la connexion est établie, vous pouvez commencer à interroger le catalogue Lakekeeper. Par exemple :

```sql theme={null}
USE demo;

SHOW TABLES;
```

Si votre installation inclut des données d’exemple (comme le jeu de données des taxis), vous devriez voir des tables comme :

```response theme={null}
┌─name──────────┐
│ default.taxis │
└───────────────┘
```

<Note>
  Si vous ne voyez aucune table, cela signifie généralement que :

  1. L’environnement n’a pas encore créé les tables d’exemple
  2. Le service de catalogue Lakekeeper n’est pas encore entièrement initialisé
  3. Le processus de chargement des données d’exemple n’est pas encore terminé

  Vous pouvez consulter les logs de Spark pour suivre la progression de la création des tables :

  ```bash theme={null}
  docker-compose logs spark
  ```
</Note>

Pour interroger une table (si elle est disponible) :

```sql theme={null}
SELECT count(*) FROM `default.taxis`;
```

```response theme={null}
┌─count()─┐
│ 2171187 │
└─────────┘
```

<Info>
  **Accents graves obligatoires**

  Les accents graves sont obligatoires, car ClickHouse ne prend pas en charge plusieurs espaces de noms.
</Info>

Pour afficher le DDL de la table :

```sql theme={null}
SHOW CREATE TABLE `default.taxis`;
```

```response theme={null}
┌─statement─────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE demo.`default.taxis`                                                             │
│ (                                                                                             │
│     `VendorID` Nullable(Int64),                                                               │
│     `tpep_pickup_datetime` Nullable(DateTime64(6)),                                           │
│     `tpep_dropoff_datetime` Nullable(DateTime64(6)),                                          │
│     `passenger_count` Nullable(Float64),                                                      │
│     `trip_distance` Nullable(Float64),                                                        │
│     `RatecodeID` Nullable(Float64),                                                           │
│     `store_and_fwd_flag` Nullable(String),                                                    │
│     `PULocationID` Nullable(Int64),                                                           │
│     `DOLocationID` Nullable(Int64),                                                           │
│     `payment_type` Nullable(Int64),                                                           │
│     `fare_amount` Nullable(Float64),                                                          │
│     `extra` Nullable(Float64),                                                                │
│     `mta_tax` Nullable(Float64),                                                              │
│     `tip_amount` Nullable(Float64),                                                           │
│     `tolls_amount` Nullable(Float64),                                                         │
│     `improvement_surcharge` Nullable(Float64),                                                │
│     `total_amount` Nullable(Float64),                                                         │
│     `congestion_surcharge` Nullable(Float64),                                                 │
│     `airport_fee` Nullable(Float64)                                                           │
│ )                                                                                             │
│ ENGINE = Iceberg('http://minio:9002/warehouse-rest/warehouse/default/taxis/', 'minio', '[HIDDEN]') │
└───────────────────────────────────────────────────────────────────────────────────────────────┘
```

<div id="loading-data-from-your-data-lake-into-clickhouse">
  ## Chargement des données de votre lac de données vers ClickHouse
</div>

Si vous devez charger des données depuis le catalogue Lakekeeper dans ClickHouse, commencez par créer une table ClickHouse locale :

```sql theme={null}
CREATE TABLE taxis
(
    `VendorID` Int64,
    `tpep_pickup_datetime` DateTime64(6),
    `tpep_dropoff_datetime` DateTime64(6),
    `passenger_count` Float64,
    `trip_distance` Float64,
    `RatecodeID` Float64,
    `store_and_fwd_flag` String,
    `PULocationID` Int64,
    `DOLocationID` Int64,
    `payment_type` Int64,
    `fare_amount` Float64,
    `extra` Float64,
    `mta_tax` Float64,
    `tip_amount` Float64,
    `tolls_amount` Float64,
    `improvement_surcharge` Float64,
    `total_amount` Float64,
    `congestion_surcharge` Float64,
    `airport_fee` Float64
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(tpep_pickup_datetime)
ORDER BY (VendorID, tpep_pickup_datetime, PULocationID, DOLocationID);
```

Chargez ensuite les données de la table de votre catalogue Lakekeeper via un `INSERT INTO SELECT` :

```sql theme={null}
INSERT INTO taxis 
SELECT * FROM demo.`default.taxis`;
```
