Je semble avoir des requêtes très lentes sur une boîte RDS de taille moyenne (DB.M3.Medium, RAM de 3,7 Go).
C'est sur une table de 4 152 928 rangées ..
select sum(some_field) c
from pages
where pages.some_id=123
and pages.first_action_at > '2014-01-01 00:00:00 +1000'
Total Runtime: 45031 MS.
Localement, j'ai environ 1,1 million de lignes et la même requête prend environ 450ms ..
Voici le plan de requête, d'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 d'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
Total Runtime: 42419.772 MS
Pour référence, 141559 Les rangées font partie de la somme ().
Les indices actuels que j'ai sont:
:some_id
:some_id, :first_action_at
work_mem
a déjà été défini sur 1 Mo (RDS par défaut). Je viens de changer cela à 18 Mo.
EDIT: Semble être résolu par le maximum work_mem
En plus d'ajouter le deuxième indice ci-dessus, la vitesse est maintenant d'environ 800 ms.
Après avoir réaffecté votre question, j'ai réalisé que vous n'exécutez pas Amazon Redshift, mais Amazon RDS, qui semble exécuter des postgres non souillés, au moins selon la documentation :
Amazon RDS prend en charge les instances de DB exécutant plusieurs versions de PostgreSQL. Nous soutenons actuellement les versions PostgreSQL 9.3.1, 9.3.2 et 9.3.3.
Cela signifierait que vous avez Anciennes en index uniquement à votre disposition. Si vous rencontrez des conditions préalables (essentiellement si vacuum
peut suivre les opérations d'écriture) et si some_field
n'est pas mis à jour à souvent et raisonnablement petit (ce qui semble être le cas pour une colonne numérique), l'index parfait comprendrait some_field
Dans la 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 d'avoir des colonnes avec des contrôles d'égalité d'abord et des gammes plus tard. Détails:
[.____] Index et performances multicolonnes
Si vous ne voyez pas "Scan d'indice uniquement" dans EXPLAIN ANALYZE
, la dernière colonne est juste un ballast et mieux à gauche:
CREATE INDEX ON pages(some_id, first_action_at);
(Comme vous l'avez maintenant, selon votre mise à jour de la question.)
De toute façon, un autre index sur juste (some_id)
offre très peu sur cet indice multicolonné:
[.____] est un indice composite également bien pour les requêtes sur le premier champ?
Tous les conseils habituels pour les requêtes lentes et la configuration du serveur approprié s'applique et a work_mem
Le réglage de 1 Mo est beaucoup trop bas pour une DB avec des millions de lignes. Mais ce paramètre particulier ne devrait pas être crucial pour cette requête particulière, puisque work_mem
est ( par documentation ):
mémoire à utiliser par des opérations de tri internes et des tables de hachage.
Ni applique ici ici.