libpq muy lento para una base de datos grande (20 millones de registros)

Soy nuevo en SQL/RDBMS.

Tengo una aplicación que agrega filas con 10 columnas en el servidor PostgreSQL usando la biblioteca libpq. En este momento, mi servidor se ejecuta en la misma máquina que mi aplicación Visual C++.

He agregado alrededor de 15-20 millones de registros. La simple consulta de obtener el recuento total lleva de 4 a 5 minutos usando select count(*) from <tableName>;.

He indexado mi tabla con la hora en que estoy ingresando los datos (código de tiempo). La mayoría de las veces necesito contar con diferentes WHERE / AND cláusulas añadidas.

¿Hay alguna manera de hacer las cosas rápido? Necesito hacerlo lo más rápido posible porque una vez que el servidor se mueva a la red, las cosas se volverán mucho más lentas.

Muchas Gracias

preguntado el 28 de julio de 12 a las 12:07

¿En qué versión de Postgres estás? -

@garfield Cada vez que publicar una pregunta, alguien le pide su versión de PostgreSQL. ¿No es eso una pista de que deberías ponlo cuando hagas la pregunta? -

Debe haber algo mal con su hardware. 5 minutos para un count(*) es demasiado largo. -

@a_horse_with_no_name Hay algún problema con el hardware, se están ejecutando consultas simultáneas o se ha inflado enormemente la tabla, sí. -

3 Respuestas

No creo que la latencia de la red sea un factor importante en la duración de su consulta. Todo el procesamiento se realiza en el servidor PostgreSQL.

El diseño de PostgreSQL MVCC significa que cada fila de la tabla, no solo los índices, debe recorrerse para calcular el conteo (*), lo cual es una operación costosa. En su caso, hay muchas filas involucradas.

Hay una buena página wiki sobre este tema aquí http://wiki.postgresql.org/wiki/Slow_Counting con sugerencias.

Dos sugerencias de este enlace, una es usar una columna de índice:

select count(index-col) from ...;

... aunque esto solo funciona en algunas circunstancias.

Si tiene más de un índice, vea cuál tiene el menor costo usando:

EXPLAIN ANALYZE select count(index-col) from ...;

Si puede vivir con un valor aproximado, otra es usar una función específica de Postgres para un valor aproximado como:

select reltuples from pg_class where relname='mytable';

La calidad de esta aproximación depende de la frecuencia con la que se configure el autovacío y muchos otros factores; ver los comentarios.

Respondido 29 Jul 12, 09:07

Pero esto puede ayudarme a obtener el recuento de la tabla total. En las entradas de la tabla, tengo una columna que aumenta secuencialmente un entero largo. El conteo total será igual al valor en esa columna de la última fila. Se puede hacer tanta optimización. Pero cuando se agrega un "dónde" y un "y" en mi consulta, aquí es donde las cosas empeoran. Además, si proporciono el nombre de la columna en mi "recuento (...)", ¿cómo hará alguna diferencia ya que nuevamente postgre tiene que revisar todas las columnas para obtener el conteo? - Garfield

Si sus columnas están indexadas, PG solo tendrá que contar las entradas del índice, no las filas completas de la tabla. Además, poner una cláusula where restringirá las filas y debería acelerar las cosas. Pruébalo. Y puedes probar diferentes índices + EXPLICAR ANALIZAR para ver qué efecto tienen. - pd40

@Garfield Cuando dices "entero largo que aumenta secuencialmente", ¿te refieres a un SEQUENCE or SERIAL / BIGSERIAL ? Porque pueden tener huecos o agujeros. El ID máximo no es necesariamente igual al número de filas, incluso si nunca ha eliminado una fila. Cada vez que haces un INSERT luego revierte la transacción, tira las identificaciones generadas, dejando un agujero. Los agujeros también pueden ocurrir de otras maneras. max(id) is no lo mismo que count(id) para agendar una serial. - craig timbre

@ pd420 En realidad, ese no es el caso. Incluso si realiza un escaneo de índice, PostgreSQL aún debe presionar el montón de la tabla para examinar los datos de visibilidad, como se explica en el artículo wiki de conteo lento al que se vinculó. Esto ha mejorado mucho con la nueva característica de "escaneos de solo índice" en 9.2, pero para versiones anteriores aún se debe verificar la visibilidad. El mapa de visibilidad en (IIRC) 8.4 y superior puede permitir tomar algunos atajos si está actualizado, pero tiene limitaciones. - craig timbre

@CraigRinger: Yo mismo no estaba del todo seguro y esperaba obtener más información de usted. :) Así que estudié el manual un poco más y es bastante complejo. reltuples se establece mediante varias operaciones. Además ANALYZEtambién por VACUUM, VACUUM FULL, CLUSER, CREATE INDEX .. y otros: Postgres aprovecha todas las oportunidades. Con mesas grandes, ANALYZE solo escanea una muestra aleatoria de páginas y guarda una estimación. El más alto statistics_target entre todas las columnas se utiliza para determinar el número de páginas en la muestra aleatoria. De esta manera, puede tener un (pequeño) efecto en la precisión de reltuples. - Erwin Brandstetter

Imagine pg_relation_size('tablename') y dividirlo por los segundos pasados ​​en

select count(*) from tablename

Eso le dará el rendimiento de su(s) disco(s) al hacer un escaneo completo de esta tabla. Si es demasiado bajo, desea concentrarse en mejorar eso en primer lugar. Tener un buen subsistema de E/S y un caché de disco del sistema operativo que funcione bien es crucial para las bases de datos.

La configuración predeterminada de Postgres está destinada a no consumir demasiados recursos para funcionar bien con otras aplicaciones. Dependiendo de su hardware y la utilización general de la máquina, es posible que desee ajustar varios parámetros de rendimiento, como búferes_compartidos, tamaño_caché_efectivo or trabajo_mem. Consulte los documentos para su versión específica y la wiki. optimización de rendimiento .

También tenga en cuenta que la velocidad de select count(*)Las consultas de estilo no tienen nada que ver con libpq o la red, ya que solo se recupera una fila resultante. Sucede completamente del lado del servidor.

Respondido 28 Jul 12, 16:07

También puede verse ralentizado por la hinchazón de la mesa, así que ten cuidado con eso. Asegúrese de que el autovacío esté funcionando con frecuencia si hace muchas updates y deletes. - craig timbre

No indica cuáles son sus datos, pero normalmente el por qué manejar tablas con una gran cantidad de datos es particionar la tabla. http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

Esto no acelerará su select count(*) from <tableName>; consulta, e incluso podría ralentizarlo, pero si normalmente solo está interesado en una parte de los datos de la tabla, esto puede ser útil.

Respondido 29 Jul 12, 02:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.