Très lent simple requête PostgreSQL sur RDS
-
11-12-2019 - |
Question
J'ai l'impression d'avoir très lente des requêtes sur un support de taille RDS boîte (db.m3.moyenne, 3,7 go de ram).
C'est à travers une table de 4,152,928 lignes..
select sum(some_field) c
from pages
where pages.some_id=123
and pages.first_action_at > '2014-01-01 00:00:00 +1000'
La durée totale d'utilisation:45031 mme.
Localement, j'ai environ 1,1 million de lignes, et la même requête prend environ 450 ms..
Voici le plan de requête, de l'expliquer:
Aggregate (cost=475640.59..475640.60 rows=1 width=4)
-> Seq Scan on pages (cost=0.00..475266.07 rows=149809 width=4)
Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone)
AND (some_id = 447))
Voici la réponse de l'expliquer, analyser:
Aggregate (cost=475641.74..475641.76 rows=1 width=4) (actual time=42419.717..42419.718 rows=1 loops=1)
-> Seq Scan on pages (cost=0.00..475267.22 rows=149810 width=4) (actual time=0.013..42265.908 rows=141559 loops=1)
Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone) AND (some_id = 447))
Rows Removed by Filter: 4011369
La durée totale d'utilisation:42419.772 ms
Pour référence, 141559 lignes font partie de la somme().
L'actuel indices que j'ai sont:
:some_id
:some_id, :first_action_at
work_mem
était précédemment fixé à 1 mo RDS (par défaut).Je viens de changer cette à 18 mo.
Edit:Semble être résolu en faisant monter work_mem
ainsi que d'ajouter le deuxième indice ci-dessus, la vitesse est désormais autour de 800 ms.
La solution
Correspondant de l'indice de
Après re-lecture de votre question, j'ai réalisé que vous ne sont pas en cours d'exécution Amazon Redshift, mais Amazon RDS, qui semble être en cours d'exécution, sans tache Postgres, au moins selon la documentation:
Amazon RDS prend en charge les instances DB exécution de plusieurs versions de PostgreSQL.Actuellement, nous utilisons les versions de PostgreSQL 9.3.1, 9.3.2 et 9.3.3.
Cela signifierait que vous avez index-analyse uniquement à votre disposition.Si vous répondez à certaines conditions préalables (en gros si vacuum
peut suivre les opérations d'écriture) et si some_field
n'est pas mis à jour souvent et de taille raisonnable (ce qui semble être le cas pour une colonne numérique), le parfait index de l'inclure some_field
en dernière position (comme @zerkms d'abord mentionné):
CREATE INDEX ON pages(some_id, first_action_at, some_field);
Notez que some_id
devrait venir avant first_action_at
, car il est généralement plus efficace pour avoir des colonnes avec l'égalité des contrôles de premier et de plages plus tard.Détails:
Index multicolonne et de la performance
Si vous ne voyez pas "index-only scan" dans EXPLAIN ANALYZE
, la dernière colonne est tout simplement de lest et laissées à l'écart:
CREATE INDEX ON pages(some_id, first_action_at);
(Comme vous l'avez maintenant, en fonction de votre question de mise à jour.)
De toute façon, un autre indice sur (some_id)
seulement n'offre que très peu au cours de cette index multicolonne:
Est un indice composite aussi bien pour les requêtes sur le premier champ?
Configuration du serveur
Tous les conseils habituels pour les requêtes lentes et la bonne configuration du serveur s'applique et un work_mem
réglage de 1 MO est beaucoup trop faible pour un DB avec des millions de lignes.Mais ce paramètre ne doit pas être cruciale pour cette question particulière, depuis work_mem
est (par la documentation):
mémoire à utiliser en interne les opérations de tri et de tables de hachage.
Ne s'applique pas ici.