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

Optimiser la plage de requêtes d'horodatage Postgres

CLUSTER

Si vous avez l'intention d'utiliser CLUSTER , la syntaxe affichée n'est pas valide.

create CLUSTER ticket USING ticket_1_idx;

Exécuter une fois :

CLUSTER ticket USING ticket_1_idx;

Cela peut aide beaucoup avec de plus grands ensembles de résultats. Pas tellement pour une seule ligne renvoyée.
Postgres se souvient de l'index à utiliser pour les appels suivants. Si votre tableau n'est pas en lecture seule, l'effet se détériore avec le temps et vous devez le réexécuter à certains intervalles :

CLUSTER ticket;

Peut-être uniquement sur des partitions volatiles. Voir ci-dessous.

Cependant , si vous avez beaucoup de mises à jour, CLUSTER (ou VACUUM FULL ) peut en fait être mauvais pour les performances. La bonne quantité de ballonnement permet UPDATE pour placer de nouvelles versions de lignes sur la même page de données et évite d'avoir à étendre trop souvent physiquement le fichier sous-jacent dans le système d'exploitation. Vous pouvez utiliser un FILLFACTOR soigneusement réglé pour obtenir le meilleur des deux mondes :

  • Facteur de remplissage pour un index séquentiel qui est PK

pg_repack

CLUSTER prend un verrou exclusif sur la table, ce qui peut être un problème dans un environnement multi-utilisateurs. Citant le manuel :

Lorsqu'une table est mise en cluster, un ACCESS EXCLUSIVE le verrou est acquis sur celui-ci. Cela empêche toute autre opération de base de données (à la fois lecture et écriture ) d'opérer sur la table jusqu'au CLUSTER est terminé.

Bold emphase mienne. Envisagez l'alternative pg_repack :

Contrairement à CLUSTER et VACUUM FULL il fonctionne en ligne, sans détenir un verrou exclusif sur les tables traitées pendant le traitement. pg_repack est efficace pour démarrer, avec des performances comparables à l'utilisation de CLUSTER directement.

et :

pg_repack doit prendre un verrou exclusif à la fin de la réorganisation.

La version 1.3.1 fonctionne avec :

PostgreSQL 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4

La version 1.4.2 fonctionne avec :

PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10

Requête

La requête est suffisamment simple pour ne pas causer de problèmes de performances en soi.

Cependant, un mot sur l'exactitude :Le BETWEEN construire inclut les frontières. Votre requête sélectionne tout le 19 décembre plus enregistrements du 20 décembre à 00h00. C'est extrêmement improbable exigence. Il y a de fortes chances que vous vouliez vraiment :

SELECT *
FROM   ticket 
WHERE  created >= '2012-12-19 0:0'
AND    created <  '2012-12-20 0:0';

Performances

Tout d'abord, vous demandez :

Pourquoi sélectionne-t-il l'analyse séquentielle ?

Votre EXPLAIN la sortie montre clairement un balayage d'index , pas une analyse de table séquentielle. Il doit y avoir une sorte de malentendu.

Si vous êtes pressé pour de meilleures performances, vous pourrez peut-être améliorer les choses. Mais les informations de base nécessaires ne sont pas dans la question. Les options possibles incluent :

  • Vous ne pouvez interroger que les colonnes requises au lieu de * pour réduire les coûts de transfert (et éventuellement d'autres avantages en termes de performances).

  • Vous pourriez regarder le partitionnement et placez des tranches de temps pratiques dans des tables séparées. Ajoutez des index aux partitions si nécessaire.

  • Si le partitionnement n'est pas une option, une autre technique connexe mais moins intrusive consisterait à ajouter un ou plusieurs index partiels .
    Par exemple, si vous interrogez principalement le mois en cours , vous pouvez créer l'index partiel suivant :

    CREATE INDEX ticket_created_idx ON ticket(created)
    WHERE created >= '2012-12-01 00:00:00'::timestamp;
    

    CREATE un nouvel index juste avant le début d'un nouveau mois. Vous pouvez facilement automatiser la tâche avec une tâche cron.Facultativement DROP index partiels pour les anciens mois plus tard.

  • Conserver l'index total en plus pour CLUSTER (qui ne peut pas fonctionner sur des index partiels). Si les anciens enregistrements ne changent jamais, le partitionnement de table aiderait beaucoup cette tâche, car vous n'avez qu'à regrouper les nouvelles partitions. Là encore, si les enregistrements ne changent jamais du tout, vous n'avez probablement pas besoin de CLUSTER .

Si vous combinez les deux dernières étapes, les performances devraient être impressionnantes.

Bases sur les performances

Il vous manque peut-être une des bases. Tous les conseils de performance habituels s'appliquent :

  • https://wiki.postgresql.org/wiki/Slow_Query_Questions
  • https://wiki.postgresql.org/wiki/Performance_Optimization