2010-10-24 7 views
6

Tengo la siguiente tabla simple que contiene datos de medición de tráfico:muy lento mapa de bits montón escanear en Postgres

CREATE TABLE "TrafficData" 
(
    "RoadID" character varying NOT NULL, 
    "DateID" numeric NOT NULL, 
    "ExactDateTime" timestamp NOT NULL, 
    "CarsSpeed" numeric NOT NULL, 
    "CarsCount" numeric NOT NULL 
) 
CREATE INDEX "RoadDate_Idx" ON "TrafficData" USING btree ("RoadID", "DateID"); 

La columna RoadID identifica de forma exclusiva el camino cuyos datos se está grabando, mientras DateId identifica el día del año (1..365) de los datos, básicamente una representación redondeada de ExactDateTime.

Tengo alrededor de 100.000.000 filas; hay 1.000 valores distintos en la columna "RoadID" y 365 valores distintos en la columna "DateID".

Luego ejecutar la siguiente consulta:

SELECT * FROM "TrafficData" 
WHERE "RoadID"='Station_1' 
AND "DateID">20100610 AND "DateID"<20100618; 

Esta toma hasta tres segundos alucinantes para terminar, y no puedo por la vida de a averiguar por qué.

EXPLAIN ANALYZE me da el siguiente resultado:

Bitmap Heap Scan on "TrafficData" (cost=104.84..9743.06 rows=2496 width=47) (actual time=35.112..2162.404 rows=2016 loops=1) 
    Recheck Cond: ((("RoadID")::text = 'Station_1'::text) AND ("DateID" > 20100610::numeric) AND ("DateID" < 20100618::numeric)) 
    -> Bitmap Index Scan on "RoadDate_Idx" (cost=0.00..104.22 rows=2496 width=0) (actual time=1.637..1.637 rows=2016 loops=1) 
     Index Cond: ((("RoadID")::text = 'Station_1'::text) AND ("DateID" > 20100610::numeric) AND ("DateID" < 20100618::numeric)) 
Total runtime: 2163.985 ms 

Mis especificaciones:

  • de Windows 7
  • Postgres 9.0
  • 4 GB de RAM

que había mucho apreciar cualquier poin útil ters!

+0

Esta no es la tabla que está utilizando, no hay una columna "StationId". –

+0

Ah, cierto; gracias por señalar eso. StationID == RoadID. Mi error. Cambié el nombre de la columna en la definición de la tabla para hacer que los contenidos fueran más intuitivos, pero no cambié el nombre en la definición de la consulta y la salida de la consulta. Actualicé la pregunta para incluir el nombre correcto de la columna. – TroutKing

+0

¿Tiene una aspiradora en funcionamiento o la ha desactivado? –

Respuesta

0
  • 4GB RAM -> 6+ tiene 100M de registros, que no son grandes pero para una memoria de máquina de escritorio podría ser importante. Si esto no es un ordenador de sobremesa, no estoy seguro de por qué tendría una cantidad tan pequeña de la memoria
  • AND "DateID">20100610 AND "DateID"<20100618; ->DateID BETWEEN 20100611 AND 20100617;
  • crear un índice en el DateId
  • Deshacerse de todas las comillas dobles campo nombres
  • en lugar de un VARCHAR, hacen RoadID un campo de texto
+0

La actualización de RAM no es una opción, desafortunadamente. Más RAM tampoco debería hacer ninguna diferencia, ya que los archivos de índice ya son lo suficientemente pequeños para cargarse en la memoria. También probé DateID ENTRE, lamentablemente no hizo diferencia. – TroutKing

+0

también desea crear un índice en el DateID; ver las adiciones – vol7ron

+0

Correcto, he agregado un índice en DateID. Lamentablemente, no hay diferencia. – TroutKing

5

la parte lenta es ir a buscar Obviosly los datos de las tablas, ya que el índice de acceso parece ser muy rápido. Puede optimizar los parámetros de uso de RAM (consulte http://wiki.postgresql.org/wiki/Performance_Optimization y http://www.varlena.com/GeneralBits/Tidbits/perf.html) u optimizar el diseño de los datos en la tabla emitiendo un comando CLUSTER (consulte http://www.postgresql.org/docs/8.3/static/sql-cluster.html).

CLUSTER "TrafficData" USING "RoadDate_Idx"; 

debería hacerlo.

+0

Probé esto ayer, pero tuve que darme por vencido cuando el comando CLUSTER todavía estaba funcionando después de once horas. – TroutKing

+2

Holla ... ¿Tal vez una selección ordenada simple en otra podría ser más rápida?Si CLUSTER es tan lento, realmente parece ser un problema, y ​​los datos no parecen coincidir con el índice en absoluto. Si puede, intente esto en hardware de clase de servidor ... – Daniel

2

Añadiendo a la respuesta de Daniel, la operación del clúster es un proceso único que reorganizó los datos en el disco. La intención es obtener sus filas de resultados de 2000 de menos bloques de disco.

Como se trata de datos ficticios, que se utilizan para averiguar cómo puede consultarlos rápidamente, recomiendo volver a cargarlos, en un patrón más parecido a cómo se cargará a medida que se genera. Imagino que los datos se generan un día a la vez, lo que resultará efectivamente en una fuerte correlación entre DateID y la ubicación en el disco. Si ese es el caso, entonces o bien agruparé por DateID, o dividiré los datos de prueba en 365 cargas por separado, y lo volveré a cargar.

Sin eso, y al tener datos generados aleatoriamente, es muy probable que tenga que realizar más de 2000 búsquedas de su cabeza de disco.

También verificaría que cualquier otra cosa que esté ejecutando en Windows 7 no esté agregando tiempo a las lecturas que no necesita, como asegurar que los bloques leídos no contengan firmas de virus, o realizar simultáneamente una desfragmentación de disco programada automáticamente (lo que hace que la cabeza del disco casi nunca esté cerca de donde estaba la última vez que se leyó un bloque de base de datos).

Cuestiones relacionadas