PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

LEFT JOIN lent sur CTE avec des intervalles de temps

L'exactitude d'abord :Je soupçonne un bogue dans votre requête :

 LEFT JOIN historical_ohlcv ohlcv ON ohlcv.time_open >= g.start_time
                                 AND ohlcv.time_close < g.end_time

Contrairement à ma réponse référencée, vous vous joignez à un intervalle de temps :(time_open, time_close] . La façon dont vous le faites exclut les lignes du tableau où l'intervalle traverse les bordures du compartiment. Seuls les intervalles entièrement contenus dans un seul bucket comptent. Je ne pense pas que ce soit voulu ?

Une solution simple consisterait à décider de l'appartenance au compartiment en fonction de time_open (ou time_close ) seule. Si vous voulez continuer à travailler avec les deux, vous devez définir exactement comment gérer les intervalles qui se chevauchent avec plusieurs compartiments.

De plus, vous recherchez max(high) par compartiment, qui est de nature différente de count(*) dans ma réponse référencée.

Et vos seaux sont de simples intervalles par heure ?

On peut alors radicalement simplifier. Travailler avec seulement time_open :

SELECT date_trunc('hour', time_open) AS hour, max(high) AS max_high
FROM   historical_ohlcv
WHERE  exchange_symbol = 'BINANCE'
AND    symbol_id = 'ETHBTC'
AND    time_open >= now() - interval '5 months'  -- frame_start
AND    time_open <  now()                        -- frame_end
GROUP  BY 1
ORDER  BY 1;

Connexe :

  • Rééchantillonner sur les données de séries temporelles

Il est difficile de parler d'une optimisation supplémentaire des performances tant que les bases ne sont pas claires. Et nous aurions besoin de plus d'informations.

Sont WHERE variables de conditions ?
Combien de valeurs distinctes dans exchange_symbol et symbol_id ?
Moy. taille de ligne ? Qu'est-ce que vous obtenez pour :

SELECT avg(pg_column_size(t)) FROM historical_ohlcv t TABLESAMPLE SYSTEM (0.1);

La table est-elle en lecture seule ?

En supposant que vous filtrez toujours sur exchange_symbol et symbol_id et les valeurs sont variables, votre table est en lecture seule ou autovacuum peut suivre la charge d'écriture afin que nous puissions espérer des analyses d'index uniquement, vous feriez mieux d'avoir un index multicolonne sur (exchange_symbol, symbol_id, time_open, high DESC) pour appuyer cette requête. Indexer les colonnes dans cet ordre. Connexe :

  • Index multicolonne et performances

En fonction de la distribution des données et d'autres détails, un LEFT JOIN LATERAL solution pourrait être une autre option. Connexe :

  • Comment trouver une moyenne de valeurs pour des intervalles de temps dans postgres
  • Optimiser la requête GROUP BY pour récupérer le dernier enregistrement par utilisateur

En dehors de tout cela, vous EXPLAIN le plan présente quelques très mauvaises estimations :

  • https://explain.depesz.com/s/E5yI

Utilisez-vous un courant version de Postgres ? Vous devrez peut-être travailler sur la configuration de votre serveur - ou au moins définir des objectifs de statistiques plus élevés sur les colonnes pertinentes et des paramètres de vide automatique plus agressifs pour la grande table. Connexe :

  • Empêcher PostgreSQL de choisir parfois un mauvais plan de requête
  • Autovacuum agressif sur PostgreSQL