Se sabe que el recuento de filas en tablas grandes es lento en PostgreSQL. Para obtener un número preciso, debe realizar un recuento completo de filas debido a la naturaleza de MVCC . Hay una manera de acelerar esto drásticamente si el recuento no tiene que ser exacto como parece ser en su caso.
En lugar de obtener el recuento exacto ( lento con tablas grandes):
SELECT count(*) AS exact_count FROM myschema.mytable;
Obtienes una estimación cercana como esta ( extremadamente rápido ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
Qué tan cerca esté la estimación depende de si corres lo ANALYZE
suficiente. Suele estar muy cerca.
Consulte las preguntas frecuentes de la Wiki de PostgreSQL .
O la página wiki dedicada para el rendimiento de conteo (*) .
Mejor todavía
El artículo en el PostgreSQL Wiki se fue un poco descuidado . Ignoró la posibilidad de que pueda haber varias tablas con el mismo nombre en una base de datos, en diferentes esquemas. Para dar cuenta de eso:
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'
O mejor aun
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Más rápido, más simple, más seguro, más elegante. Consulte el manual sobre tipos de identificadores de objetos .
Úselo to_regclass('myschema.mytable')
en Postgres 9.4+ para evitar excepciones para nombres de tablas no válidos:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Como comentó @a_horse , la cláusula recién agregada para el SELECT
comando podría ser útil si las estadísticas en pg_class
no están lo suficientemente actualizadas por alguna razón. Por ejemplo:
- No
autovacuum
correr.
- Inmediatamente después de un gran
INSERT
o DELETE
.
TEMPORARY
tablas (que no están cubiertas por autovacuum
).
Esto solo mira una selección aleatoria de bloques n % ( 1
en el ejemplo) y cuenta las filas en ella. Una muestra más grande aumenta el costo y reduce el error, su elección. La precisión depende de más factores:
- Distribución del tamaño de las filas. Si un bloque dado tiene filas más anchas de lo habitual, el recuento es más bajo de lo habitual, etc.
- Tuplas muertas o un
FILLFACTOR
espacio ocupado por bloque. Si se distribuye de manera desigual en la tabla, es posible que la estimación sea incorrecta.
- Errores generales de redondeo.
En la mayoría de los casos, la estimación de pg_class
será más rápida y precisa.
Respuesta a la pregunta real
Primero, necesito saber el número de filas en esa tabla, si el recuento total es mayor que alguna constante predefinida,
Y si ...
... es posible en el momento en que el conteo pase mi valor constante, se detendrá el conteo (y no esperará a terminar el conteo para informar que el conteo de filas es mayor).
Si. Puede usar una subconsulta conLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres realmente deja de contar más allá del límite dado, obtiene un recuento exacto y actual para hasta n filas (500000 en el ejemplo) y n de lo contrario. Sin pg_class
embargo, no tan rápido como la estimación .