2 votos

¿El ejemplo de código de geocode() en PostGIS tiger geocoder geocodifica todos los registros y luego limita intencionadamente?

En geocode función en PostGIS tigre geocoder extensión tienen un ejemplo de geocodificación por lotes que parece ser utilizado por muchas personas. Sin embargo no estoy seguro si el comportamiento de este ejemplo que observé es intencional.

UPDATE addresses_to_geocode SET (rating, new_address, lon, lat) = ( COALESCE((g.geo).rating,-1), pprint_addy((g.geo).addy), ST_X((g.geo).geomout)::numeric(8,5), ST_Y((g.geo).geomout)::numeric(8,5) ) FROM (SELECT addid FROM addresses_to_geocode WHERE rating IS NULL ORDER BY addid LIMIT 3) As a LEFT JOIN (SELECT addid, (geocode(address,1)) As geo FROM addresses_to_geocode As ag WHERE ag.rating IS NULL ORDER BY addid LIMIT 3) As g ON a.addid = g.addid WHERE a.addid = addresses_to_geocode.addid;

El código de ejemplo se suponía que sólo geocodificar 3 direcciones que no ser geocodificado luego actualizar la tabla. Así que usted puede ejecutar este código una y otra vez, cada vez que se actualizará 3 filas.

Con una tabla de 10 direcciones, el código de ejemplo necesita 18 segundos para ejecutarse (sabía que el rendimiento en mi configuración no es bueno, solía ser mucho mejor cuando sólo tenía datos de 3 estados en SSD. Ahora tengo 100G de datos en un disco duro normal y es mucho más lento), y 10 segundos en la segunda ejecución.

Con una tabla de 20 direcciones, necesita 45 s para ejecutarse, 40 s para la 2ª ejecución. Con una tabla de 500 direcciones, sigue funcionando antes de que lo cancele.

Esto me hace creer que el código de ejemplo en realidad geocodifica primero todas las filas de la tabla y luego elige los 3 primeros resultados para actualizar la tabla.

He observado este tipo de comportamiento antes con limit :

SELECT geocode(address_string,1) FROM address_sample LIMIT 4;

tardará mucho más tiempo si la mesa es grande. Mientras que esta línea siempre utiliza un tiempo similar sin importar el tamaño de la tabla:

SELECT geocode(sample.address_string, 1) 
    FROM (SELECT address_string FROM address_sample LIMIT 4) as sample;

Así que he modificado el código de ejemplo en esto:

UPDATE address_table SET (rating, output_address, lon, lat, geomout) = ( COALESCE((a.geo).rating,-1), pprint_addy((a.geo).addy), ST_X((a.geo).geomout)::numeric(8,5), ST_Y((a.geo).geomout)::numeric(8,5), (a.geo).geomout) FROM (SELECT sample.addid, geocode(sample.input_address,1) as geo from (select addid, input_address from address_table WHERE rating IS NULL ORDER BY addid LIMIT 3) as sample ) as a WHERE a.addid = address_table.addid;

Ahora siempre se ejecuta en 5 segundos sin importar el tamaño de la tabla. Sin embargo, hay un nuevo problema: la primera fila de mi tabla es una dirección incorrecta. El código original asignará la calificación como -1 cuando no pueda encontrar una coincidencia, entonces las ejecuciones posteriores omitirán esta dirección mala. Mi versión modificada no actualizó la columna de calificación como -1, por lo que cada ejecución intentará geocodificarla y saltársela.

En resumen, en realidad tengo dos preguntas:

  1. ¿Es intencionado el comportamiento que he observado en el código de ejemplo? El documento dice

    para un gran número de direcciones que no desea actualizar todas a la vez, ya que todo el geocódigo debe confirmarse a la vez.

No estoy seguro de lo que esto significa. Si siempre geocodifica toda la tabla, ¿por qué limita la salida?

  1. ¿Cómo hacer que mi versión modificada establezca la columna de calificación de la dirección incorrecta como -1?

EDIT: He resuelto mi segunda pregunta.

En LEFT JOIN en el código de ejemplo es necesario para devolver una tabla de resultados que con la mala calificación de dirección como -1. El nuevo código se ejecuta 3~4 segundos para 3 filas cada vez, sin importar el tamaño de la tabla.

UPDATE address_table SET (rating, output_address, lon, lat, geomout) = ( COALESCE((g.geo).rating,-1), pprint_addy((g.geo).addy), ST_X((g.geo).geomout)::numeric(8,5), ST_Y((g.geo).geomout)::numeric(8,5), (g.geo).geomout) FROM (select addid from address_table WHERE rating IS NULL ORDER BY addid LIMIT 3) as a left join (SELECT sample.addid, geocode(sample.input_address,1) as geo from (select addid, input_address from address_table WHERE rating IS NULL ORDER BY addid LIMIT 3) as sample ) as g on a.addid = g.addid WHERE a.addid = address_table.addid;

EDITAR 2 : He ejecutado los comandos de vacío siguiendo la sugerencia de @LR1234567. No mejoró el rendimiento general de geocodificación, pero el código de ejemplo ahora tienen un rendimiento similar con mi versión modificada. ¿Tal vez el uso en el código de ejemplo depende de la limpieza del esquema de tigre?

EDITAR 3 : El código de ejemplo sigue teniendo problemas. Mis datos tienen una dirección no válida (con código postal incompleto) en la primera fila. El código de ejemplo tardará una eternidad en ejecutarse si se inicia desde la primera fila, y ese tiempo está directamente relacionado con el tamaño de la tabla, 271 segundos para una tabla de 100 filas. Una vez procesada esta fila inválida y marcada como -1, el código de ejemplo puede procesar las filas normales en un tiempo razonable. Sin embargo mi código modificado puede procesar la fila inválida en 4 segundos.

La única diferencia entre el código de ejemplo y mi versión es que en la cláusula from, en lugar de en la cláusula where, hago un subconjunto de la tabla.

EDITAR4 Aquí están los resultados del análisis de las explicaciones que verificaron mi observación:

  1. El código de ejemplo se ejecuta en una tabla de 100 filas por primera vez, con la dirección de la primera fila inválida:

El primer paso del escaneado tarda 284 s para 99 filas de geocodificación

The first step of scan take 284 s for 99 rows of geocoding

el segundo paso de limitar a 3 filas ocurrió después, demasiado tarde

the second step of limit to 3 rows happened after, too late

  1. Mi código modificado para la misma tabla:

El primer paso de la geocodificación sólo procesó 3 filas

The first step of geocoding only processed 3 rows

el segundo paso del límite en realidad tienen el mismo tiempo de inicio y final de la primera etapa, por lo que se produjeron juntos

the second step of limit actually have same starting and end time of first step, so they happened together

  1. Una vez marcada la primera fila de direcciones no válidas con -1, ejecute de nuevo el código de ejemplo para las demás filas:

las filas se limitaron antes de la geocodificación

the rows were limited before geocoding

Así que esto podría ser algo relacionado con cómo PostgreSQL planificación de la consulta si hay una fila no válida. Tal vez las otras personas no tenían la fila inválida en la parte superior entonces no encontraron este problema. Ordené mi dirección de entrada por código postal para que la fila no válida apareciera en la parte superior.

3voto

dlanod Puntos 8661

Espero que esto responda a sus preguntas

1) No quieres geocodificar toda una tabla a la vez debido a la forma en que funciona Postgres. Todo el trabajo en una actualización se confirma como una sola transacción, lo que significa dos cosas

a) Si por cualquier motivo la actualización se bloquea en mitad del proceso, perderá todo el trabajo realizado en esa actualización.

b) Dado que postgres realiza todos los commits como una única transacción, se está reteniendo mucha memoria y recursos durante el periodo de la actualización y en cierto punto ralentiza las cosas.

2) Tus tiempos parecen bastante malos. ¿Ejecutó el análisis de vacío en toda la jerarquía?

como se detalla en - http://postgis.net/docs/postgis_installation.html#install_tiger_geocoder_extension

SELECT install_missing_indexes();
vacuum analyze verbose tiger.addr;
vacuum analyze verbose tiger.edges;
vacuum analyze verbose tiger.faces;
vacuum analyze verbose tiger.featnames;
vacuum analyze verbose tiger.place;
vacuum analyze verbose tiger.cousub;
vacuum analyze verbose tiger.county;
vacuum analyze verbose tiger.state;

2voto

dracodoc Puntos 118

Con más experimentos y análisis de explicaciones, descubrí que:

  1. Si hay una dirección no válida (con código postal incompleto) en la primera fila, el código de ejemplo geocodificará toda la tabla y luego limitará la salida.

El primer paso del escaneado tarda 284 s para 99 filas de geocodificación. Ver más detalles en EDIT 4 en mi pregunta.

The first step of scan take 284 s for 99 rows of geocoding

  1. Mi versión modificada no tiene este problema.
  2. Si muevo la dirección inválida a la 2ª fila, el código de ejemplo no tiene este problema.
  3. Si la dirección inválida ha sido procesada y marcada con -1, el código de ejemplo tampoco tiene este problema.

Por lo tanto, este comportamiento involuntario sólo se produce cuando hay una dirección no válida en la primera fila. No estoy seguro de si ocurrirá aleatoriamente cuando la dirección no válida se encuentre en medio de la tabla, porque no estoy seguro de por qué se produjo el comportamiento problemático en primer lugar. Así que voy a utilizar mi versión modificada de todos modos.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X