Na potrzeby tego zadania skorzystałem z danych Postcodes from UK które można pobrać tutaj http://ovh.to/73NLuDk, plik postcodes.csv rozmiar 275mb, ilość rekordów 2 532 817.
CREATE TABLE postcodes (
postcode VARCHAR,
status VARCHAR,
usertype VARCHAR,
easting FLOAT,
northing FLOAT,
positional_quality_indicator FLOAT,
country VARCHAR,
latitude FLOAT,
longitude FLOAT,
postcode_no_space VARCHAR,
postcode_fixed_width_seven VARCHAR,
postcode_fixed_width_eight VARCHAR,
postcode_area VARCHAR,
postcode_district VARCHAR,
postcode_sector VARCHAR,
outcode VARCHAR,
incode VARCHAR
);
AB1 0AA,terminated,small,385386,801193,1,Scotland,57.101474,-2.242851,AB10AA,AB1 0AA,AB1 0AA,AB,AB1,AB1 0,AB1,0AA
Wszystkie polecenia znajdują się w pliku https://github.com/artkolinski/NoSQL/blob/master/scripts/postgresAll.sql Uruchamiamy bazę danych, tworzymy tabelę skryptem https://github.com/artkolinski/NoSQL/blob/master/scripts/create.sql oraz włączamy pomiar czasu.
\i create.sql;
\timing;
Kopiujemy dane z pliku CSV do bazy
COPY postcodes FROM ' C:\postcodes.csv ' DELIMITER ',' CSV;
COPY 2532817
Czas: 11002,358 ms
Sprawdzamy ile jest rekordów
SELECT COUNT(*) FROM postcodes;
count
---------
2532817
(1 wiersz)
Czas: 370,137 ms
Wybieramy kurs wschodni oraz północny dla kodu ‘WR3 8AS’
select easting, northing from postcodes where postcode = 'WR3 8AS';
easting | northing
---------+----------
384785 | 256819
(1 wiersz)
Czas: 296,812 ms
Szukamy dystryktu kodu pocztowego ‘M1 1AA’:
select postcode_district from postcodes where postcode_fixed_width_eight = 'M1 1AA';
postcode_district
-------------------
M1
(1 wiersz)
Czas: 408,702 ms
Szukamy współrzędnych geograficznych dla kodu ‘RG46SU’:
select latitude, longitude from postcodes where postcode_no_space = 'RG46SU';
latitude | longitude
-----------+-----------
51.470889 | -0.918018
(1 wiersz)
Czas: 383,943 ms
Teraz chcemy znaleźć kurs wschodni oraz północny wieży w Londynie “The Tower of London” w celu dalszej bardziej ciekawej obróbki:
select easting, northing from postcodes where postcode = 'EC3N 4AB';
easting | northing
---------+----------
533602 | 180570
(1 wiersz)
Czas: 285,792 ms
Szukamy 10 najbliższych kodów pocztowych dla “The Tower of London” oraz obliczamy ich odległość:
select postcode, sqrt(pow(abs(533668 - easting),2) + pow(abs(180551 - northing),2)) as distance from postcodes order by distance limit 10;
postcode | distance
----------+------------------
EC3N 4AE | 68.6804193347711
EC3N 4AB | 68.6804193347711
EC3N 4AQ | 85.7962703152066
EC3N 4AD | 99.9849988748312
E1W 1AY | 111.162043881893
E1W 1XA | 111.162043881893
E1W 1XE | 111.162043881893
E1W 1UU | 111.162043881893
E1W 1UY | 111.162043881893
E1W 1UN | 111.162043881893
(10 wierszy)
Czas: 1311,928 ms
Zmieniamy trochę polecenie aby uzyskać tylko aktywne kody w obszarze 1km x 1km od “The Tower of London” ale bez kodu “The Tower of London” którym jest ‘EC3N 4AB’:
select postcode, sqrt(pow(abs(533668 - easting),2) + pow(abs(180551 - northing),2)) as distance from postcodes where status = 'live' and easting between 533668 - 500 and 533668 + 500 and northing between 180551 - 500 and 180551 + 500 and postcode != 'EC3N 4AB' order by distance limit 10;
postcode | distance
----------+------------------
EC3N 4AE | 68.6804193347711
E1W 1YL | 111.162043881893
E1W 1AY | 111.162043881893
E1W 1XB | 111.162043881893
E1W 1UN | 111.162043881893
E1W 1LE | 125.251746494809
E1W 1DD | 135.594985158006
E1W 1BA | 145.248063670398
EC3N 4DR | 196.468827043885
E1W 1LD | 220.67623342807
(10 wierszy)
Czas: 342,497 ms
Zrobienie wykresu dla ostatniego polecenia:
COPY(select postcode, sqrt(pow(abs(533668 - easting),2) + pow(abs(180551 - northing),2)) as distance from postcodes where status = 'live' and easting between 533668 - 500 and 533668 + 500 and northing between 180551 - 500 and 180551 + 500 and postcode != 'EC3N 4AB' order by distance) to 'D:\chart.csv' with CSV HEADER;
COPY 286
Czas: 825,638 ms
Użycie RStudio do rysowania
dane <- read.csv('chart.csv', sep=',')
plot(dane$postcode, dane$distance, cex = 0.5, main="Postcode / Distance", xlab = "Postcode ", ylab = "Distance", las = 1)
Do importu danych z csv użyłem programu logstash-5.3.0, mój skrypt importujący wygląda następująco:
input {
stdin {
type => "stdin-type"
}
file {
path => ["C:/postcodes.csv"]
start_position => "beginning"
}
}
filter {
csv {
columns => ["postcode","status","usertype","easting","northing","positional_quality_indicator","country","latitude","longitude","postcode_no_space","postcode_fixed_width_seven","postcode_fixed_width_eight","postcode_area","postcode_district","postcode_sector","outcode","incode"]
separator => ","
}
}
output {
stdout { codec => rubydebug }
elasticsearch {
hosts => "localhost:9200"
index => "csv_index"
}
}
Czas importu ~32min
Sprawdzenie liczby zaimportowanych danych
curl -XGET localhost:9200/csv_index/_count
{"count":2532817,"_shards":{"total":5,"successful":5,"failed":0}}
Sprawdzmy czy maping został dokonany prawidłowo podczas importu
curl -s "http://localhost:9200/csv_index/"
{"csv_index":{"aliases":{},"mappings":{"logs":{"properties":{"@timestamp":{"type":"date"},"@version":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"country":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"easting":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"host":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"incode":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"latitude":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"longitude":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"message":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"northing":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"outcode":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"path":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"positional_quality_indicator":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_area":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_district":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_fixed_width_eight":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_fixed_width_seven":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_no_space":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"postcode_sector":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"status":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"usertype":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}}},"settings":{"index":{"creation_date":"1491224430222","number_of_shards":"5","number_of_replicas":"1","uuid":"163JkMJDQQWRL7otLJLejw","version":{"created":"5020299"},"provided_name":"csv_index"}}}}
Szukamy kodu ‘M11AA’:
curl -s "http://localhost:9200/csv_index/_search?pretty=true&q=postcode_no_space:'M11AA'"
{
"took" : 21,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 12.727802,
"hits" : [
{
"_index" : "csv_index",
"_type" : "logs",
"_id" : "AVsz8J-1mvZBZk3K4IVs",
"_score" : 12.727802,
"_source" : {
"postcode_district" : "M1",
"country" : "England",
"easting" : "385022",
"positional_quality_indicator" : "1",
"latitude" : "53.487362",
"postcode_fixed_width_eight" : "M1 1AA",
"postcode" : "M1 1AA",
"usertype" : "large",
"message" : "M1 1AA,terminated,large,385022,398985,1,England,53.487362,-2.227197,M11AA,M1 1AA,M1 1AA,M,M1,M1 1,M1,1AA",
"northing" : "398985",
"path" : "C:/postcodes.csv",
"postcode_sector" : "M1 1",
"@timestamp" : "2017-04-03T13:10:59.054Z",
"postcode_fixed_width_seven" : "M1 1AA",
"outcode" : "M1",
"@version" : "1",
"host" : "DESKTOP-MJ9FGTH",
"postcode_area" : "M",
"postcode_no_space" : "M11AA",
"incode" : "1AA",
"status" : "terminated",
"longitude" : "-2.227197"
}
}
]
}
}
Szukamy kodu ‘RG46SU’:
curl -s "http://localhost:9200/csv_index/_search?pretty=true&q=postcode_no_space:'RG46SU'"
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 12.728338,
"hits" : [
{
"_index" : "csv_index",
"_type" : "logs",
"_id" : "AVsz9K54mvZBZk3K6NHf",
"_score" : 12.728338,
"_source" : {
"postcode_district" : "RG4",
"country" : "England",
"easting" : "475249",
"positional_quality_indicator" : "1",
"latitude" : "51.470889",
"postcode_fixed_width_eight" : "RG4 6SU",
"postcode" : "RG4 6SU",
"usertype" : "large",
"message" : "RG4 6SU,live,large,475249,175213,1,England,51.470889,-0.918018,RG46SU,RG4 6SU,RG4 6SU,RG,RG4,RG4 6,RG4,6SU",
"northing" : "175213",
"path" : "C:/postcodes.csv",
"postcode_sector" : "RG4 6",
"@timestamp" : "2017-04-03T13:15:24.975Z",
"postcode_fixed_width_seven" : "RG4 6SU",
"outcode" : "RG4",
"@version" : "1",
"host" : "DESKTOP-MJ9FGTH",
"postcode_area" : "RG",
"postcode_no_space" : "RG46SU",
"incode" : "6SU",
"status" : "live",
"longitude" : "-0.918018"
}
}
]
}
}
Szukamy współrzędnych geograficznych dla kodu ‘RG46SU’:
Curl -s "http://localhost:9200/csv_index/_search?pretty=true&q=postcode_no_space:'RG46SU'&filter_path=took,hits.hits._source.longitude,hits.hits._source.latitude"
{
"took" : 2,
"hits" : {
"hits" : [
{
"_source" : {
"latitude" : "51.470889",
"longitude" : "-0.918018"
}
}
]
}
}
Teraz chcemy znaleźć współrzędne wieży w Londynie “The Tower of London”:
Curl -s "http://localhost:9200/csv_index/_search?pretty=true&q=postcode_no_space:'EC3N4AB'&filter_path=took,hits.hits._source.latitude,hits.hits._source.longitude"
{
"took" : 2,
"hits" : {
"hits" : [
{
"_source" : {
"latitude" : "51.470889",
"longitude" : "-0.918018"
}
}
]
}
}
Następnie chcemy znaleźć kurs wschodni oraz północny wieży w Londynie “The Tower of London”:
Curl -s "http://localhost:9200/csv_index/_search?pretty=true&q=postcode_no_space:'EC3N4AB'&filter_path=took,hits.hits._source.easting,hits.hits._source.northing"
{
"took" : 2,
"hits" : {
"hits" : [
{
"_source" : {
"easting" : "533602",
"northing" : "180570"
}
}
]
}
}
| Zadanie | Czas ElasticSearch | Czas PostgreSQL |
|---|---|---|
| import danych 2,5mln | 32min | 11s |
| wyszukanie ‘M11AA’ | 21ms | 408ms |
| wyszukanie ‘RG46SU’ | 2ms | 380ms |
| wyszukanie ‘RG46SU’ | ||
| lat / lon | 2ms | 383ms |
| wyszukanie ‘EC3N4AB’ | ||
| lat / lon | 2ms | 285ms |
| wyszukanie ‘EC3N4AB’ | ||
| easting/northing | 2ms | 290ms |
Skala ocen 1-10 (więcej = lepiej)
| Kryteria | ElasticSearch | PostgreSQL |
|---|---|---|
| import danych | 2 | 10 |
| latwość użycia | 5 | 7 |
| predkość nauki | 1 | 8 |
| czas odpowiedzi | 10 | 1 |
| czas tworzenia zap. | 1 | 9 |