Com que rapidez devo esperar que o PostGIS codifique geograficamente endereços bem formatados?


17

Com que rapidez devo esperar que o PostGIS codifique geograficamente endereços bem formatados?

Eu instalei o PostgreSQL 9.3.7 e o PostGIS 2.1.7, carreguei os dados de nação e todos os dados de estados, mas descobrimos que o geocodificação é muito mais lento do que eu imaginava. Estabeleci minhas expectativas muito altas? Estou recebendo uma média de 3 geocódigos individuais por segundo. Preciso fazer cerca de 5 milhões e não quero esperar três semanas por isso.

Esta é uma máquina virtual para processar matrizes R gigantes e eu instalei esse banco de dados na lateral para que a configuração possa parecer um pouco boba. Se uma grande alteração na configuração da VM ajudar, eu posso alterar a configuração.

Especificações de hardware

Memória: processadores de 65GB: 6 lscpume fornece o seguinte:

# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                6
On-line CPU(s) list:   0-5
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             6
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 58
Stepping:              0
CPU MHz:               2400.000
BogoMIPS:              4800.00
Hypervisor vendor:     VMware
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              30720K
NUMA node0 CPU(s):     0-5

OS é centos, uname -rvdá o seguinte:

# uname -rv
2.6.32-504.16.2.el6.x86_64 #1 SMP Wed Apr 22 06:48:29 UTC 2015

Configuração do Postgresql

> select version()
"PostgreSQL 9.3.7 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11), 64-bit"
> select PostGIS_Full_version()
POSTGIS="2.1.7 r13414" GEOS="3.4.2-CAPI-1.8.2 r3921" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.2, released 2012/10/08" LIBXML="2.7.6" LIBJSON="UNKNOWN" TOPOLOGY RASTER"

Com base nas sugestões anteriores para esses tipos de consultas, eu atualizei shared_bufferso postgresql.confarquivo para cerca de 1/4 da RAM disponível e o tamanho do cache efetivo para 1/2 da RAM:

shared_buffers = 16096MB     
effective_cache_size = 31765MB

Eu tenho installed_missing_indexes()e (depois de resolver inserções duplicadas em algumas tabelas) não tive nenhum erro.

Exemplo de geocodificação do SQL nº 1 (lote) ~ o tempo médio é de 2,8 / s

Estou seguindo o exemplo de http://postgis.net/docs/Geocode.html , que me permite criar uma tabela contendo o endereço para geocodificar e, em seguida, executando um SQL UPDATE:

UPDATE addresses_to_geocode
              SET  (rating, longitude, latitude,geo) 
              = ( COALESCE((g.geom).rating,-1),
              ST_X((g.geom).geomout)::numeric(8,5), 
              ST_Y((g.geom).geomout)::numeric(8,5),
              geo )
              FROM (SELECT "PatientId" as PatientId
              FROM addresses_to_geocode 
              WHERE "rating" IS NULL ORDER BY PatientId LIMIT 1000) As a
              LEFT JOIN (SELECT "PatientId" as PatientId, (geocode("Address",1)) As geom
              FROM addresses_to_geocode As ag
              WHERE ag.rating IS NULL ORDER BY PatientId LIMIT 1000) As g ON a.PatientId = g.PatientId
              WHERE a.PatientId = addresses_to_geocode."PatientId";

Estou usando um tamanho de lote de 1000 acima e ele retorna em 337,70 segundos. É um pouco mais lento para lotes menores.

Exemplo 2 de geocodificação do SQL (linha por linha) ~ o tempo médio é de 1,2 / s

Quando eu cavo em meus endereços, executando os códigos geográficos, um de cada vez, com uma declaração parecida com esta (btw, o exemplo abaixo levou 4,14 segundos),

SELECT g.rating, ST_X(g.geomout) As lon, ST_Y(g.geomout) As lat, 
    (addy).address As stno, (addy).streetname As street, 
    (addy).streettypeabbrev As styp, (addy).location As city, 
    (addy).stateabbrev As st,(addy).zip 
FROM geocode('6433 DROMOLAND Cir NW, MASSILLON, OH 44646',1) As g;

é um pouco mais lento (2,5x por registro), mas posso observar a distribuição dos tempos de consulta e ver que são uma minoria de consultas demoradas que diminuem mais esse número (apenas os primeiros 2600 de 5 milhões têm tempos de pesquisa). Ou seja, os 10% principais estão demorando em média cerca de 100 ms, os 10% inferiores em média 3,69 segundos, enquanto a média é 754 ms e a mediana é 340 ms.

# Just some interaction with the data in R
> range(lookupTimes[1:2600])
[1]  0.00 11.54
> median(lookupTimes[1:2600])
[1] 0.34
> mean(lookupTimes[1:2600])
[1] 0.7541808
> mean(sort(lookupTimes[1:2600])[1:260])
[1] 0.09984615
> mean(sort(lookupTimes[1:2600],decreasing=TRUE)[1:260])
[1] 3.691269
> hist(lookupTimes[1:2600]

Tempos de geocodificação para as primeiras 2600 linhas

Outros pensamentos

Se eu não conseguir um aumento de ordem de magnitude no desempenho, imaginei que poderia pelo menos adivinhar sobre a previsão de tempos de geocódigo lentos, mas não me é óbvio por que os endereços mais lentos parecem demorar muito mais. Estou executando o endereço original por meio de uma etapa de normalização personalizada para garantir que ele esteja bem formatado antes da geocode()função:

sql=paste0("select pprint_addy(normalize_address('",myAddress,"'))")

onde myAddressé uma [Address], [City], [ST] [Zip]cadeia de caracteres compilada a partir de uma tabela de endereços do usuário a partir de um banco de dados não postgresql.

Eu tentei (falhei) instalar a pagc_normalize_addressextensão, mas não está claro se isso trará o tipo de melhoria que estou procurando. Editado para adicionar informações de monitoramento conforme a sugestão

atuação

Uma CPU está vinculada: [editar, apenas um processador por consulta, então eu tenho 5 CPUs não utilizadas]

top - 14:10:26 up 1 day,  3:11,  4 users,  load average: 1.02, 1.01, 0.93
Tasks: 219 total,   2 running, 217 sleeping,   0 stopped,   0 zombie
Cpu(s): 15.4%us,  1.5%sy,  0.0%ni, 83.1%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65056588k total, 64613476k used,   443112k free,    97096k buffers
Swap: 262139900k total,    77164k used, 262062736k free, 62745284k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 3130 postgres  20   0 16.3g 8.8g 8.7g R 99.7 14.2 170:14.06 postmaster
11139 aolsson   20   0 15140 1316  932 R  0.3  0.0   0:07.78 top
11675 aolsson   20   0  135m 1836 1504 S  0.3  0.0   0:00.01 wget
    1 root      20   0 19364 1064  884 S  0.0  0.0   0:01.84 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.06 kthreadd

Amostra de atividade do disco na partição de dados enquanto um proc está indexado a 100%: [editar: apenas um processador em uso por esta consulta]

# dstat -tdD dm-3 1
----system---- --dsk/dm-3-
  date/time   | read  writ
12-06 14:06:36|1818k 3632k
12-06 14:06:37|   0     0
12-06 14:06:38|   0     0
12-06 14:06:39|   0     0
12-06 14:06:40|   0    40k
12-06 14:06:41|   0     0
12-06 14:06:42|   0     0
12-06 14:06:43|   0  8192B
12-06 14:06:44|   0  8192B
12-06 14:06:45| 120k   60k
12-06 14:06:46|   0     0
12-06 14:06:47|   0     0
12-06 14:06:48|   0     0
12-06 14:06:49|   0     0
12-06 14:06:50|   0    28k
12-06 14:06:51|   0    96k
12-06 14:06:52|   0     0
12-06 14:06:53|   0     0
12-06 14:06:54|   0     0 ^C

Analise esse SQL

Isto é EXPLAIN ANALYZEdessa consulta:

"Update on addresses_to_geocode  (cost=1.30..8390.04 rows=1000 width=272) (actual time=363608.219..363608.219 rows=0 loops=1)"
"  ->  Merge Left Join  (cost=1.30..8390.04 rows=1000 width=272) (actual time=110.934..324648.385 rows=1000 loops=1)"
"        Merge Cond: (a.patientid = g.patientid)"
"        ->  Nested Loop  (cost=0.86..8336.82 rows=1000 width=184) (actual time=10.676..34.241 rows=1000 loops=1)"
"              ->  Subquery Scan on a  (cost=0.43..54.32 rows=1000 width=32) (actual time=10.664..18.779 rows=1000 loops=1)"
"                    ->  Limit  (cost=0.43..44.32 rows=1000 width=4) (actual time=10.658..17.478 rows=1000 loops=1)"
"                          ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode addresses_to_geocode_1  (cost=0.43..195279.22 rows=4449758 width=4) (actual time=10.657..17.021 rows=1000 loops=1)"
"                                Filter: (rating IS NULL)"
"                                Rows Removed by Filter: 24110"
"              ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode  (cost=0.43..8.27 rows=1 width=152) (actual time=0.010..0.013 rows=1 loops=1000)"
"                    Index Cond: ("PatientId" = a.patientid)"
"        ->  Materialize  (cost=0.43..18.22 rows=1000 width=96) (actual time=100.233..324594.558 rows=943 loops=1)"
"              ->  Subquery Scan on g  (cost=0.43..15.72 rows=1000 width=96) (actual time=100.230..324593.435 rows=943 loops=1)"
"                    ->  Limit  (cost=0.43..5.72 rows=1000 width=42) (actual time=100.225..324591.603 rows=943 loops=1)"
"                          ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode ag  (cost=0.43..23534259.93 rows=4449758000 width=42) (actual time=100.225..324591.146 rows=943 loops=1)"
"                                Filter: (rating IS NULL)"
"                                Rows Removed by Filter: 24110"
"Total runtime: 363608.316 ms"

Veja melhor detalhamento em http://explain.depesz.com/s/vogS


1
O que a máquina faz quando você executa as consultas? Ele bloqueia o IO ou o gargalo está em outro lugar?
til_b 12/06/2015

1
Quantos estados você carregou. Eu geralmente chego de 30ms a 150ms por endereço em uma caixa de 64 bits do Windows com 4-8GB de RAM. Normalmente, embora eu esteja trabalhando apenas com 1 ou 2 estados. Ainda não avaliamos o impacto de mais estados no desempenho.
LR1234567

@ LR1234567 50 states
aaryno

1
A CPU @til_b está atrelada a 99,7%
aaryno 12/06

Parece que vamos esperar as duas semanas necessárias para concluir isso, já que é uma coisa única e que teremos bastante suco quando terminar para acompanhar a carga de tempo de execução de 100 endereços / dia Nós estamos experimentando. Manterei isso em aberto até terminarmos, caso algo realmente interessante aconteça, que nos permita contornar nossas CPUs vinculadas.
aaryno

Respostas:


7

Passei muito tempo experimentando isso, acho melhor postar separadamente, pois eles são de ângulos diferentes.

Este é realmente um tópico complexo. Veja mais detalhes no meu post sobre a configuração do servidor de geocodificação e o script que usei . Aqui estão apenas alguns breves resumos:

Um servidor com apenas dados de 2 estados é sempre mais rápido que um servidor carregado com todos os dados de 50 estados.

Verifiquei isso com meu PC doméstico em momentos diferentes e em dois servidores Amazon AWS diferentes.

Meu servidor de camada livre da AWS com dados de 2 estados possui apenas 1G de RAM, mas possui um desempenho consistente de 43 a 59 ms para dados com 1000 registros e 45.000 registros.

Usei exatamente o mesmo procedimento de configuração para um servidor AWS 8G RAM com todos os estados carregados, exatamente o mesmo script e dados, e o desempenho caiu para 80 ~ 105 ms.

Minha teoria é que, quando o geocoder não pode corresponder exatamente ao endereço, ele começou a ampliar o alcance da pesquisa e a ignorar parte, como CEP ou cidade. É por isso que o documento de geocódigo se vangloria de que pode recolonizar o endereço com CEP incorreto, embora demorasse 3000 ms.

Com apenas 2 dados de estados carregados, o servidor levará muito menos tempo na pesquisa infrutífera ou em uma correspondência com pontuação muito baixa, porque só pode pesquisar em 2 estados.

Tentei limitar isso definindo o restrict_regionparâmetro para multipolígonos de estado na função de geocódigo, esperando evitar a pesquisa infrutífera, pois tenho certeza de que a maioria dos endereços tem o estado correto. Compare estas duas versões:

  select geocode('501 Fairmount DR , Annapolis, MD 20137',1); 
  select geocode('501 Fairmount DR , Annapolis, MD 20137', 1, the_geom) from tiger.state where statefp = '24';

A única diferença feita pela segunda versão é que, normalmente, se eu executar a mesma consulta imediatamente novamente, será muito mais rápido porque os dados relacionados foram armazenados em cache, mas a segunda versão desativou esse efeito.

Portanto, o restrict_regionnão está funcionando como eu desejava, talvez apenas tenha sido usado para filtrar o resultado de vários hits, não para limitar os intervalos de pesquisa.

Você pode ajustar um pouco o seu postgre conf.

O suspeito habitual de instalar índices ausentes, a análise de vácuo, não fez nenhuma diferença para mim, porque o script de download já fez a manutenção necessária, a menos que você tenha mexido com eles.

No entanto, definir o postgre conf de acordo com este post ajudou. Meu servidor em escala real com 50 estados estava com 320 ms com configuração padrão para alguns dados com pior formato, melhorou para 185 ms com 2G shared_buffer, cache 5G e foi para 100 ms ainda mais com a maioria das configurações ajustadas de acordo com esse post.

Isso é mais relevante para o postgis e suas configurações pareciam semelhantes.

O tamanho do lote de cada confirmação não importa muito para o meu caso. A documentação do geocódigo usava um tamanho de lote 3. Experimentei valores de 1, 3, 5 a 10. Não encontrei nenhuma diferença significativa com isso. Com um tamanho de lote menor, você faz mais confirmações e atualizações, mas acho que o gargalo real não está aqui. Na verdade, estou usando o lote 1 agora. Como sempre há algum endereço incorreto e inesperado causará exceção, definirei o lote inteiro com o erro como ignorado e continuarei pelas linhas restantes. Com o tamanho do lote 1, não preciso processar a tabela na segunda vez para codificar geograficamente os possíveis bons registros no lote marcado como ignorado.

Obviamente, isso depende de como o script em lote funciona. Vou postar meu script com mais detalhes mais tarde.

Você pode tentar usar o endereço de normalização para filtrar o endereço incorreto, se for adequado ao seu uso. Eu vi alguém mencionar isso em algum lugar, mas não tinha certeza de como isso funciona, pois a função normalizar funciona apenas no formato. Na verdade, não posso dizer qual endereço é inválido.

Mais tarde, percebi que se o endereço estiver obviamente em mau estado e você quiser ignorá-lo, isso poderá ajudar. Por exemplo, tenho muitos endereços com nomes de ruas ausentes ou mesmo nomes de ruas. A normalização de todos os endereços primeiro será relativamente rápida e, em seguida, você poderá filtrar o endereço incorreto óbvio e ignorá-los. No entanto, isso não combina com o meu uso, pois um endereço sem número de rua ou nome de rua ainda pode ser mapeado para a rua ou cidade, e essas informações ainda são úteis para mim.

E a maioria dos endereços que não podem ser geocodificados no meu caso realmente tem todos os campos, apenas não há correspondência no banco de dados. Você não pode filtrar esses endereços apenas normalizando-os.

EDITAR Para obter mais detalhes, consulte minha postagem no blog sobre a configuração do servidor de geocodificação e o script que eu usei .

EDIÇÃO 2 Concluí a geocodificação de 2 milhões de endereços e fiz muita limpeza nos endereços com base no resultado da geocodificação. Com uma entrada melhor limpa, o próximo trabalho em lotes está sendo executado muito mais rápido. Por limpeza, quero dizer que alguns endereços estão obviamente errados e devem ser removidos ou com conteúdo inesperado para o geocoder causar problemas na geocodificação. Minha teoria é: a remoção de endereços incorretos pode evitar atrapalhar o cache, o que melhora significativamente o desempenho em bons endereços.

Separei a entrada com base no estado para garantir que todo trabalho possa ter todos os dados necessários para geocodificação em cache na RAM. No entanto, todo endereço incorreto no trabalho faz com que o geocodificador procure em mais estados, o que pode atrapalhar o cache.


Ótima resposta. Na minha caixa, por exemplo, a filtragem de estado acelera a correspondência em torno de um fator de 50 (!), Mas desconfio que possa ter problemas de índice.
achou

2
  1. De acordo com este tópico de discussão , você deve usar o mesmo procedimento de normalização para processar os dados do Tiger e seu endereço de entrada. Como os dados do Tiger foram processados ​​com o normalizador interno, é melhor usar apenas o normalizador interno. Mesmo que você tenha funcionado com o pagc_normalizer, ele pode não ser útil se você não o usar para atualizar os dados do Tiger.

    Dito isto, acho que geocode () chamará o normalizador de qualquer maneira, para normalizar o endereço antes que a geocodificação possa não ser realmente útil. Um uso possível do normalizador pode ser comparar o endereço normalizado e o endereço retornado pelo geocode (). Com os dois normalizados, seria mais fácil encontrar o resultado incorreto de geocodificação.

    Se você pode filtrar o endereço incorreto do geocode pelo normalizador, isso realmente ajudará. No entanto, não vejo que o normalizador tenha algo como pontuação ou classificação da partida.

  2. O mesmo tópico de discussão também mencionou uma opção de depuração geocode_addresspara mostrar mais informações. O nó geocode_addressprecisa de entrada de endereço normalizada.

  3. O geocoder é rápido para a correspondência exata, mas leva muito mais tempo para casos difíceis. Descobri que existe um parâmetro restrict_regione pensei que talvez ele limite a pesquisa infrutífera se eu definir o limite como estado, pois tenho certeza em qual estado ele estará. o endereço correto, embora demore algum tempo.

    Portanto, talvez o geocodificador procure em todos os lugares possíveis se a primeira pesquisa exata não corresponder. Isso permite processar entradas com alguns erros, mas também torna algumas pesquisas muito lentas.

    Eu acho que é bom para um serviço interativo aceitar entradas com erros, mas às vezes podemos desistir de um pequeno conjunto de endereços errados para ter um melhor desempenho na geocodificação em lote.


Qual foi o impacto restrict_regionno tempo quando você definiu o estado correto? Além disso, a partir do tópico postgis-users ao qual você vinculou acima, eles mencionam especificamente problemas com endereços como os 1020 Highway 20que eu encontrei também.
Aaryno 29/10/2015

A definição do estado correto provavelmente não melhorará, pois se o endereço estiver bem formatado, o geocoder poderá acertar o estado de qualquer maneira.
Dracodoc 30/10

1

Vou postar esta resposta, mas espero que outro colaborador ajude a detalhar o seguinte, o que acho que criará uma imagem mais coerente:

Qual é o impacto do número de estados carregados na geocodificação? Eu tenho todos os 50 e estou com um desempenho muito menor do que o @ LR1234567 (ou seja, 8x por vez geocode).

Qual é o método mais eficiente para geocodificação em massa? Estou executando um processo serial, executando lotes de 100 repetidamente até que todo o backload esteja concluído. Uma abordagem multithread seria preferível, mas quais abordagens são recomendadas?

Qual é o impacto da virtualização na geocodificação do PostgreSQL? Suponho que 10% seja baseado em outras postagens, mas tenha pouca confiança nessa resposta

Agora minha resposta, que é apenas uma anedota:

O melhor que estou recebendo (com base em uma única conexão) é uma média de 208 ms por geocode. Isso é medido pela seleção aleatória de endereços do meu conjunto de dados, que se estende pelos EUA. Inclui alguns dados sujos, mas os mais antigos geocodenão parecem ruins de maneiras óbvias.

A essência disso é que pareço estar vinculado à CPU e que uma única consulta está vinculada a um único processador. Eu posso paralelizar isso tendo várias conexões em execução com UPDATEsegmentos complementares da addresses_to_geocodetabela em teoria. Enquanto isso, estou tendo geocodeuma média de 208 ms no conjunto de dados em todo o país. A distribuição é distorcida tanto em termos de onde está a maioria dos meus endereços quanto em quanto tempo eles estão demorando (por exemplo, veja o histograma acima) e a tabela abaixo.

Até agora, minha melhor abordagem é fazer isso em lotes de 10000, com algumas melhorias estimadas em fazer mais por lote. Para lotes de 100, eu estava recebendo cerca de 251ms, com 10000, obtendo 208ms.

UPDATE addresses_to_geocode 
SET (rating, longitude, latitude, geo) = 
   (COALESCE((g.geom).rating,-1), 
            ST_X((g.geom).geomout)::numeric(8,5),   
            ST_Y((g.geom).geomout)::numeric(8,5), 
            geo) 
   FROM (
       SELECT "PatientId" as PatientId 
       FROM addresses_to_geocode  
       WHERE "rating" IS NULL 
       ORDER BY PatientId LIMIT 100) As a 
   LEFT JOIN (
       SELECT "PatientId" as PatientId, (geocode("Address",1)) As geom 
       FROM addresses_to_geocode As ag 
       WHERE ag.rating IS NULL 
       ORDER BY PatientId LIMIT 100) As g 
   ON a.PatientId = g.PatientId 
   WHERE a.PatientId = addresses_to_geocode."PatientId";

Preciso citar nomes de campos por causa de como o RPostgreSQL cria as tabelas com dbWriteTable

Isso é cerca de 4x mais rápido do que se eu fizesse um registro de cada vez. Quando eu os faço um de cada vez, posso obter uma divisão por estado (veja abaixo). Fiz isso para verificar e verificar se um ou mais dos estados do TIGER tinham uma carga ou índice ruim, o que eu esperava resultar em um geocodedesempenho ruim no estado. Obviamente, tenho alguns dados ruins (alguns endereços são mesmo endereços de email!), Mas a maioria deles está bem formatada. Como eu disse antes, algumas das consultas mais antigas não apresentam deficiências óbvias em seu formato. Abaixo está uma tabela do número, tempo mínimo de consulta, tempo médio de consulta e tempo máximo de consulta para estados de 3000 - alguns endereços aleatórios do meu conjunto de dados:

       state   n  min      mean   max
1          .   1 0.00 0.0000000  0.00
12        DC   6 0.07 0.0900000  0.10
9  CHIHUAHUA   1 0.16 0.1600000  0.16
2         00   1 0.18 0.1800000  0.18
6         AR   1 0.37 0.3700000  0.37
27        MT  17 0.14 0.4229412  1.01
14        GA  37 0.22 0.4340541  2.78
10        CO   1 0.54 0.5400000  0.54
16        IL 390 0.16 0.5448974  3.75
8         CA 251 0.17 0.5546614  3.58
5         AL   4 0.13 0.5575000  0.86
18        KS   3 0.43 0.5966667  0.75
23        ME 121 0.14 0.6266116  7.88
35        SC 390 0.14 0.6516923  6.88
24        MI  62 0.12 0.6524194  3.36
40        WA   3 0.23 0.7500000  1.41
32        OK 145 0.17 0.7538621  5.84
20        LA   1 0.76 0.7600000  0.76
31        OH 551 0.00 0.7623775 10.27
17        IN 108 0.19 0.7864815  3.64
43      <NA>  89 0.00 0.8152809  4.98
15        IA   1 0.82 0.8200000  0.82
30        NY 227 0.19 0.8227753 28.47
19        KY   3 0.56 0.8333333  1.36
36        TN 333 0.11 0.8566667  6.45
28        NC 129 0.24 0.8843411  4.07
13        FL  70 0.28 0.9131429  4.65
7         AZ 101 0.20 0.9498020  6.33
34        PA  56 0.14 0.9594643  3.61
29        NJ   1 1.03 1.0300000  1.03
33        OR 101 0.24 1.0966337 14.89
26        MS  28 0.25 1.1503571 11.89
3          9   6 0.58 1.2133333  1.93
4         AK   1 1.25 1.2500000  1.25
22        MD   9 0.50 1.3055556  4.17
25        MO  22 0.31 1.3381818  4.20
42        WY   1 1.38 1.3800000  1.38
38        VA 127 0.20 1.3873228  5.69
37        TX   4 0.53 1.4800000  3.28
21        MA   4 0.47 1.5725000  3.63
11        CT   5 0.38 1.6760000  4.68
39        VT   1 2.25 2.2500000  2.25
41        WI   2 2.27 2.2850000  2.30
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.