# Recherche d'optimisation des requêtes DuckDB

**URL:** <https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870>\
**Category:** Développement\
**Created:** [Décembre 14, 2025, 9:44 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870 "2025-12-14T09:44:55Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Terdious](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/terdious/32/6316_2.png) [@Terdious](https://community.gladysassistant.com/u/Terdious)\
**Post date:** [Décembre 14, 2025, 9:44 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/1 "2025-12-14T09:44:55Z")

</div>

Suite aux discussions menées sur le verrouillage de mémoire RAM par DuckDB, il serait opportun de vérifier si nous pouvons optimiser les requête les plus lourdes.

~~La pagination est l’une des réflexions à mener.~~

Ci-dessous pour exemple l’une de mes pages les plus lourdes pour le suivi des énergies, chaque graphique contenant 8 courbes (susceptibles d’être augmentée par ailleurs) et le tout étant détaillé pour chaque phases (L1/L2/L3) + le total.

Les visualisations temporelles jusque 3 mois est fluide. Mais l’affichage à l’année est plus lente, soit environ 10s.

Requete initiale à l’affichage du dashboard avec des graphiques sur la dernière heure :

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/7/e/7efaf5b2fced811cd888724f7ac248aa99cc53cb.png)  
Début de chargement au passage à l’année sur le 1er graphique  
 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/0/5/0545cbdbe2386f05497f39862fe483f862ee033e.png)  
Fin de chargement  
 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/7/7/77bcb9a8a79c254974b7051625276fe90ac16443.png)  
Détail requête  
 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/b/8/b8480c6d54e372286c0f63fc008b9297f1adfc21.png)  
Détail temporel de la requete  
 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/3/d/3de4ce90bce32680ea44afd844657ae273d456f5.png)

Suite à la mise à jour 4.66.3, je confirme que je mets «&nbsp;seulement&nbsp;» 1s de plus pour l’affichage à l’année et aucune différence ressentie pour le reste :

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/2/5/2557fb062c6d631ac1d62fc89b1988c9e0e89b12.png)

@pierre-gilles, n’hésite pas à me dire si tu veux d’autres détails

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [Décembre 14, 2025, 9:51 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/2 "2025-12-14T09:51:51Z")

</div>

> [@Terdious](#):
>
> La pagination est l’une des réflexions à mener.

Pas besoin de pagination, on fait de l’échantillonnage, on ne renvoie que max 300 lignes par graphique 🙂

Je vais regarder avec ces informations, merci pour le post détaillé !

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [Décembre 14, 2025, 10:05 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/3 "2025-12-14T10:05:05Z")

</div>

Est-ce que tu peux faire des tests sur ta base ?

J’aimerais voir ce que ça donne avec cette requête :

```auto
SELECT
    TIME_BUCKET(INTERVAL ? MINUTES, created_at) AS created_at,
    AVG(value) AS value,
    MAX(value) AS max_value,
    MIN(value) AS min_value,
    SUM(value) AS sum_value,
    COUNT(value) AS count_value
FROM
    t_device_feature_state
WHERE device_feature_id = ?
AND created_at > ?
GROUP BY 1
ORDER BY created_at;

```

Il faut remplacer les `?` :

- Le premier remplace le par 1752
- Le deuxième par le device\_feature\_id le plus complet que tu as
- Le troisième par la date d’il y a un an, soit `'2024-12-14T10:04:11.478Z'`

Si tu veux comparer, voilà la requête actuelle:

```auto
  WITH intervals AS (
        SELECT
            created_at,
            value,
            NTILE(300) OVER (ORDER BY created_at) AS interval
        FROM
            t_device_feature_state
        WHERE device_feature_id = ?
        AND created_at > ?
    )
    SELECT
        MIN(created_at) AS created_at,
        AVG(value) AS value,
        MAX(value) AS max_value,
        MIN(value) AS min_value,
        SUM(value) AS sum_value,
        COUNT(value) AS count_value
    FROM
        intervals
    GROUP BY
        interval
    ORDER BY
        created_at;

```

---

<div class="post-metadata">

**Author:** ![Terdious](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/terdious/32/6316_2.png) [@Terdious](https://community.gladysassistant.com/u/Terdious)\
**Post date:** [Décembre 14, 2025, 10:59 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/4 "2025-12-14T10:59:52Z")

</div>

Une question, pourquoi 1752 ? Cela fait des buckets de 29h12 ??

Sinon, voilà les résultats :

1. **Agrégation par bucket temporel - Requete TimeBucket**

```auto
SELECT
    TIME_BUCKET(INTERVAL 1752 MINUTES, created_at) AS created_at,
    AVG(value) AS value,
    MAX(value) AS max_value,
    MIN(value) AS min_value,
    SUM(value) AS sum_value,
    COUNT(value) AS count_value
FROM
    t_device_feature_state
WHERE
    device_feature_id = 'e9079170-4654-4fad-b726-23a36c793905'
    AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
GROUP BY 1
ORDER BY created_at;

```

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/4/3/437ab422614a54ca9c96355edcea778f95dde605.png)  
**Résultat**

- **301 lignes retournées**
- Temps d’exécution ≈ **0,486 s**
- Buckets temporels fixes (~29h)

1. **Découpage par quantiles - Requete NTILE(300)**

```auto
WITH intervals AS (
    SELECT
        created_at,
        value,
        NTILE(300) OVER (ORDER BY created_at) AS interval
    FROM
        t_device_feature_state
    WHERE
        device_feature_id = 'e9079170-4654-4fad-b726-23a36c793905'
        AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
)
SELECT
    MIN(created_at) AS created_at,
    AVG(value) AS value,
    MAX(value) AS max_value,
    MIN(value) AS min_value,
    SUM(value) AS sum_value,
    COUNT(value) AS count_value
FROM
    intervals
GROUP BY
    interval
ORDER BY
    created_at;

```

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/5/5/5538ad01c471466da9c6ae8c443d309eb22adcad.png)  
**Résultat**

- **300 lignes retournées**
- Temps d’exécution ≈ **0,370 s**
- Intervalles équilibrés en nombre de points

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [Décembre 14, 2025, 11:05 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/5 "2025-12-14T11:05:16Z")

</div>

> [@Terdious](#):
>
> Une question, pourquoi 1752 ? Cela fait des buckets de 29h12 ??

Exact ! C’est 525600/300 😃

Par contre, la performance n’est pas meilleure, et les deux sont même plutôt bonnes niveau performance…

Après, dans ton graphique, tu as 10 fonctionnalités, donc il faut faire \* 10, ce qui explique tes performances.

La solution n’est peut-être pas là, mais peut-être sur une requête commune pour 10 fonctionnalités

---

<div class="post-metadata">

**Author:** ![Terdious](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/terdious/32/6316_2.png) [@Terdious](https://community.gladysassistant.com/u/Terdious)\
**Post date:** [Décembre 14, 2025, 11:43 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/6 "2025-12-14T11:43:49Z")

</div>

Bon bah, je viens de faire des tests … Et comme ça je dirais que le problème n’est surement pas les requetes à DuckDB (je crois d’ailleurs qu’on avait déjà fait ce genre de tests directement en dev dans Gladys ^^). Ce doit être simplement le rendu ou plutot la construction des séries … :

1. **Agrégation par bucket temporel - Requete TimeBucket**

```auto
SELECT
    device_feature_id,
    TIME_BUCKET(INTERVAL 1752 MINUTES, created_at) AS created_at,
    AVG(value) AS value,
    MAX(value) AS max_value,
    MIN(value) AS min_value,
    SUM(value) AS sum_value,
    COUNT(value) AS count_value
FROM t_device_feature_state
WHERE device_feature_id IN (
	'eaa982b7-a3c8-4b4d-b2d0-5a5cf5245938',
    'e9079170-4654-4fad-b726-23a36c793905',
    'c59fca37-54f3-418b-b27c-857e08e2a0fb',
    'da79df66-dcff-438e-859c-39b641fd15e9',
    '5eba10ac-4c3a-479c-aba7-a1e74a00d914',
    '4b5e90f0-a86b-405b-8ca1-953705ef79a3',
    'c92f8fa3-d841-4692-bd3a-e5addb760a73',
    'b5445f10-7aa9-41bf-8cae-d2f30498652f',
    '08e90478-4bb2-4a08-986f-3d6f212c95f1',
    '85311f8c-334f-4b7e-8294-2b841c0b8fe8'
)
AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
GROUP BY
    device_feature_id,
    created_at
ORDER BY
    device_feature_id,
    created_at;

```

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/0/3/03156fc80391394c9cd1e059b23e23d0bbaf5bda.png)

1. **Découpage par quantiles - Requete NTILE(300)**

```auto
WITH intervals AS (
    SELECT
        device_feature_id,
        created_at,
        value,
        NTILE(300) OVER (
            PARTITION BY device_feature_id
            ORDER BY created_at
        ) AS interval
    FROM t_device_feature_state
    WHERE device_feature_id IN (
		'eaa982b7-a3c8-4b4d-b2d0-5a5cf5245938',
	    'e9079170-4654-4fad-b726-23a36c793905',
	    'c59fca37-54f3-418b-b27c-857e08e2a0fb',
	    'da79df66-dcff-438e-859c-39b641fd15e9',
	    '5eba10ac-4c3a-479c-aba7-a1e74a00d914',
	    '4b5e90f0-a86b-405b-8ca1-953705ef79a3',
	    'c92f8fa3-d841-4692-bd3a-e5addb760a73',
	    'b5445f10-7aa9-41bf-8cae-d2f30498652f',
	    '08e90478-4bb2-4a08-986f-3d6f212c95f1',
	    '85311f8c-334f-4b7e-8294-2b841c0b8fe8'
    )
    AND created_at > TIMESTAMP '2024-12-14 10:04:11.478'
)
SELECT
    device_feature_id,
    MIN(created_at) AS created_at,
    AVG(value) AS value,
    MAX(value) AS max_value,
    MIN(value) AS min_value,
    SUM(value) AS sum_value,
    COUNT(value) AS count_value
FROM intervals
GROUP BY
    device_feature_id,
    interval
ORDER BY
    device_feature_id,
    created_at;

```

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/c/3/c34827b72bee91c705126a9ff8b2b28313346e79.png)

J’ai donc refait un test de performance sur le dashboard :

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/f/c/fccdc99590c41f0e10713ca5355b59b9267f8ec8.png)

**Etude ChatGPT ^^ :**

## 🔍 Lecture directe de ton enregistrement Performance

### ⏱ Durée totale

- **Total ≈ 13 190 ms** (13,2 s)

### 📊 Répartition (panneau de gauche)

- **Affichage (Rendering)** : **2 330 ms**
- **Rendu (Paint / Layout)** : **791 ms**
- **Script (JS)** : **563 ms**
- **Chargement réseau** : **27 ms**
- **Système / non attribué** : **~5 200 ms**
- **Total “utile” visible** : ~4 s
- **Gros trou “non attribué / idle / attente”** : ~9 s

👉 **Conclusion immédiate** :  
❌ ce n’est **ni le réseau** ,  
❌ ni DuckDB,  
❌ ni le JavaScript pur,  
👉 c’est **majoritairement du temps d’attente avant que le rendu utile démarre**.

* * *

## 🔎 Focus sur la partie Réseau (clé pour Gladys)

Dans ton tableau à droite :

- Requête : `aggregated_states (10.5.0.227)`
- **Taille transférée** : **213 ko**
- **Temps d’exécution** : **~260 ms**

👉 Ça confirme ce qu’on soupçonnait :

- la requête backend est **rapide**
- le payload est **raisonnable**
- **\< 300 ms** , donc **pas le problème**

➡ On peut désormais dire **sans ambiguïté** :

> Les 10–13 secondes **ne viennent pas des requêtes DuckDB**.

* * *

## 🧠 Où se perdent alors les ~9 secondes ?

D’après le flame chart et la timeline :

### 1️⃣ Phase “attente / non attribuée” (~9 s)

C’est typiquement :

- attente d’un **state React complet**
- attente que **toutes les séries soient prêtes**
- synchronisation avant montage du graphique
- ou logique type :
  - “on attend toutes les promesses”
  - “on attend que X soit calculé avant de rendre”

👉 **Anti-pattern classique** sur les dashboards complexes.

* * *

### 2️⃣ Phase “Rendering + Layout” (~3 s)

Là, on est clairement sur :

- **beaucoup de points**
- **beaucoup de séries**
- probablement :
  - recalcul d’échelles
  - recalcul de légendes
  - tooltips
  - min/max
  - animations

👉 C’est cohérent avec un graphe annuel multi-courbes.

## 🧾 Conclusion (que tu peux déjà formuler)

Tu peux déjà dire, preuves à l’appui :

> Les mesures Chrome Performance montrent que :
> 
> - la requête backend est \< 300 ms
> - le payload est ~213 ko
> - le JS pur \< 600 ms
> 
> Les ~13 s ressenties sont principalement dues à une phase d’attente + rendu graphique côté front.  
> L’optimisation doit donc se faire majoritairement sur le **pipeline de rendu React / graphe** , pas sur DuckDB.

## 🧭 Prochaines pistes concrètes (si tu veux aller plus loin)

Sans même voir le code, les leviers évidents sont :

- rendre le graphe **progressivement** (séries une par une)
- limiter le nombre de points **avant** le rendu (hard cap)
- désactiver animations / transitions sur les vues longues
- virtualiser / canvas pur si ce n’est pas déjà le cas

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [Décembre 14, 2025, 11:53 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/7 "2025-12-14T11:53:10Z")

</div>

Je suis pas d’accord avec ChatGPT, on voit bien dans tes captures d’écrans que c’est la réponse backend qui prend 11 secondes à répondre :

> [@Terdious](#):
>
> ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/2/5/2557fb062c6d631ac1d62fc89b1988c9e0e89b12.png)

Ce qui n’est pas étonnant, tu m’as montré qu’une requête mettait 400-500ms, donc 500 ms \* 10 = 5 secondes au mieux 🙂

> [@Terdious](#):
>
> Découpage par quantiles - Requete NTILE(300)

Justement, tu prouves mon point : pour l’instant, on ne fait pas une requête avec 10 IDs, on fait 10 requêtes séparées !

---

<div class="post-metadata">

**Author:** ![Terdious](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/terdious/32/6316_2.png) [@Terdious](https://community.gladysassistant.com/u/Terdious)\
**Post date:** [Décembre 14, 2025, 11:58 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/8 "2025-12-14T11:58:44Z")

</div>

Ok, je comprends en effet.  
Voici le résultat pour les 10 requetes séparées :

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/5/e/5e8875d02dab91082ed87cdb8a9ee9cf799ebc68.png)

Je suis sur les mêmes features que la courbe affichées

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [Décembre 14, 2025, 1:04 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/9 "2025-12-14T13:04:43Z")

</div>

> [@Terdious](#):
>
> Voici le résultat pour les 10 requetes séparées :

Ça prouve plutôt le point, vu qu’il faut prendre en compte que quand tu affiches ton tableau de bord, tu n’as pas juste ce widget, mais potentiellement 5 autres widgets, donc on est plus sur 50 requêtes 🙂

---

<div class="post-metadata">

**Author:** ![Terdious](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/terdious/32/6316_2.png) [@Terdious](https://community.gladysassistant.com/u/Terdious)\
**Post date:** [Décembre 14, 2025, 1:08 UTC](https://community.gladysassistant.com/t/recherche-doptimisation-des-requetes-duckdb/9870/10 "2025-12-14T13:08:48Z")

</div>

Oui oui, je suis en accord avec ce que tu dis !!

> [@pierre-gilles](#):
>
> qu’il faut prendre en compte que quand tu affiches ton tableau de bord, tu n’as pas juste ce widget, mais potentiellement 5 autres widgets, donc on est plus sur 50 requêtes 🙂

Mmmmh ça pas d’accord, puisque l’affichage à l’année est envoyer après le 1er chargement (affichage à l’heure au refresh de la page). Lorsque je sélectionne le graph à l’année, je n’active que celui-ci. On voit d’ailleurs bien ensuite les autres requetes ‹&nbsp;live&nbsp;› s’ajouter et se mettre en attente à la suite.

Mais je suis ok pour dire qu’actuellement on est plus de l’ordre de 3 à 5s d’attente de requetes DuckDB.
