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

Meilleur moyen d'obtenir le nombre de résultats avant l'application de LIMIT

SQL pur

Les choses ont changé depuis 2008. Vous pouvez utiliser une fonction de fenêtre pour obtenir le nombre complet et le résultat limité en une seule requête. Introduit avec PostgreSQL 8.4 en 2009.

SELECT foo
     , count(*) OVER() AS full_count
FROM   bar
WHERE  <some condition>
ORDER  BY <some col>
LIMIT  <pagesize>
OFFSET <offset>;

Notez que cela peut être considérablement plus cher que sans le nombre total . Toutes les lignes doivent être comptées, et un éventuel raccourci prenant uniquement les lignes supérieures d'un index correspondant peut ne plus être utile.
N'a pas beaucoup d'importance avec les petites tables ou full_count <=OFFSET + LIMIT . Importe pour un full_count sensiblement plus grand .

Étui d'angle :quand OFFSET est au moins aussi grand que le nombre de lignes de la requête de base, aucune ligne est retourné. Donc, vous n'obtenez pas non plus de full_count . Variante possible :

  • Exécutez une requête avec un LIMIT/OFFSET et obtenez également le nombre total de lignes

Séquence d'événements dans un SELECT requête

( 0. Les CTE sont évalués et matérialisés séparément. Dans Postgres 12 ou version ultérieure, le planificateur peut intégrer ces sous-requêtes similaires avant de commencer à travailler.) Pas ici.

  1. WHERE clause (et JOIN conditions, bien qu'aucune dans votre exemple) filtre les lignes qualifiantes de la ou des tables de base. Le reste est basé sur le sous-ensemble filtré.

( 2. GROUP BY et les fonctions d'agrégation iraient ici.) Pas ici.

( 3. Autre SELECT les expressions de liste sont évaluées, sur la base de colonnes groupées / agrégées.) Pas ici.

  1. Les fonctions de la fenêtre sont appliquées en fonction du OVER clause et la spécification de trame de la fonction. Le simple count(*) OVER() est basé sur toutes les lignes éligibles.

  2. ORDER BY

( 6. DISTINCT ou DISTINCT ON irait ici.) Pas ici.

  1. LIMIT / OFFSET sont appliqués en fonction de l'ordre établi pour sélectionner les lignes à renvoyer.

LIMIT / OFFSET devient de plus en plus inefficace avec un nombre croissant de lignes dans la table. Envisagez d'autres approches si vous avez besoin de meilleures performances :

  • Optimiser la requête avec OFFSET sur une grande table

Alternatives pour obtenir le décompte final

Il existe des approches complètement différentes pour obtenir le nombre de lignes affectées (pas le compte complet avant OFFSET &LIMIT ont été appliqués). Postgres a une comptabilité interne du nombre de lignes affectées par la dernière commande SQL. Certains clients peuvent accéder à ces informations ou compter eux-mêmes les lignes (comme psql).

Par exemple, vous pouvez récupérer le nombre de lignes affectées dans plpgsql immédiatement après l'exécution d'une commande SQL avec :

GET DIAGNOSTICS integer_var = ROW_COUNT;

Détails dans le manuel.

Ou vous pouvez utiliser pg_num_rows en PHP . Ou des fonctions similaires dans d'autres clients.

Connexe :

  • Calculer le nombre de lignes affectées par la requête par lots dans PostgreSQL