Le comptage des lignes dans les grandes tables est connu pour être lent dans PostgreSQL. Pour obtenir un nombre précis, il doit effectuer un décompte complet des lignes en raison de la nature du MVCC . Il existe un moyen d' accélérer considérablement ce processus si le décompte ne doit pas être exact comme il semble l'être dans votre cas.
Au lieu d'obtenir le décompte exact ( lent avec de grandes tables):
SELECT count(*) AS exact_count FROM myschema.mytable;
Vous obtenez une estimation précise comme celle-ci ( extrêmement rapide ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
La précision de l'estimation dépend du fait que vous en exécutez ANALYZE
suffisamment. C'est généralement très proche.
Consultez la FAQ du wiki PostgreSQL .
Ou la page wiki dédiée pour les performances de count (*) .
Mieux encore
L'article paru dans le Wiki PostgreSQL est était un peu bâclé . Il a ignoré la possibilité qu'il puisse y avoir plusieurs tables du même nom dans une base de données - dans différents schémas. Pour en tenir compte:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
Ou mieux encore
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Plus rapide, plus simple, plus sûr, plus élégant. Consultez le manuel sur les types d'identificateurs d'objets .
Utilisez to_regclass('myschema.mytable')
dans Postgres 9.4+ pour éviter les exceptions pour les noms de table non valides:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Comme @a_horse l'a commenté , la clause nouvellement ajoutée pour la SELECT
commande peut être utile si les statistiques de pg_class
ne sont pas assez actuelles pour une raison quelconque. Par exemple:
- Pas de
autovacuum
course.
- Immédiatement après un gros
INSERT
ou DELETE
.
TEMPORARY
tables (qui ne sont pas couvertes par autovacuum
).
Cela ne regarde qu'une sélection aléatoire de n % ( 1
dans l'exemple) de blocs et compte les lignes. Un plus grand échantillon augmente le coût et réduit l'erreur, votre choix. La précision dépend de plusieurs facteurs:
- Répartition de la taille des lignes. Si un bloc donné contient des lignes plus larges que d'habitude, le nombre est inférieur à la normale, etc.
- Tuples morts ou un
FILLFACTOR
espace occupé par bloc. Si elle est inégalement répartie sur le tableau, l'estimation peut être erronée.
- Erreurs d'arrondi générales.
Dans la plupart des cas, l'estimation de pg_class
sera plus rapide et plus précise.
Réponse à la question réelle
Tout d'abord, j'ai besoin de connaître le nombre de lignes dans cette table, si le nombre total est supérieur à une constante prédéfinie,
Et si c'est ...
... est possible au moment où le comptage passe ma valeur constante, cela arrêtera le comptage (et n'attendra pas de terminer le comptage pour informer que le nombre de lignes est supérieur).
Oui. Vous pouvez utiliser une sousLIMIT
- requête avec :
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres arrête réellement de compter au-delà de la limite donnée, vous obtenez un exact et actuel pour jusqu'à n lignes (500000 dans l'exemple), et n sinon. Pas aussi rapide que l'estimation pg_class
, cependant.