Ho un database (couchDB) con circa 90k di documenti al suo interno. I documenti sono molto semplici come questo:filtri molto lenti con couchDB anche con erlang
{
"_id": "1894496e-1c9e-4b40-9ba6-65ffeaca2ccf",
"_rev": "1-2d978d19-3651-4af9-a8d5-b70759655e6a",
"productName": "Cola"
}
ora voglio un giorno per sincronizzare questo database con un dispositivo mobile. Ovviamente i documenti 90k non dovrebbero andare al telefono tutti in una volta. Questo è il motivo per cui ho scritto funzioni di filtro. Questi dovrebbero filtrare per "productName". Inizialmente in Javascript successivamente in Erlang per ottenere prestazioni. Queste funzioni di filtro simile a questa in JavaScript:
{
"_id": "_design/local_filters",
"_rev": "11-57abe842a82c9835d63597be2b05117d",
"filters": {
"by_fanta": "function(doc, req){ if(doc.productName == 'Fanta'){ return doc;}}",
"by_wasser": "function(doc, req){if(doc.productName == 'Wasser'){ return doc;}}",
"by_sprite": "function(doc, req){if(doc.productName == 'Sprite'){ return doc;}}"
}
}
e come questo in Erlang:
{
"_id": "_design/erlang_filter",
"_rev": "74-f537ec4b6508cee1995baacfddffa6d4",
"language": "erlang",
"filters": {
"by_fanta": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Fanta\">> -> true; _ -> false end end.",
"by_wasser": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Wasser\">> -> true; _ -> false end end.",
"by_sprite": "fun({Doc}, {Req}) -> case proplists:get_value(<<\"productName\">>, Doc) of <<\"Sprite\">> -> true; _ -> false end end."
}
}
di mantenerlo semplice non v'è ancora alcuna richiesta, ma una stringa "hardcoded". Il filtro funziona tutto. Il problema è che sono un modo per rallentare. Ho scritto un programma di prova prima in Java in seguito in Perl per testare il tempo necessario per filtrare i documenti. Ecco uno dei miei script Perl:
$dt = DBIx::Class::TimeStamp->get_timestamp();
$content = get("http://127.0.0.1:5984/mobile_product_test/_changes?filter=local_filters/by_sprite");
$dy = DBIx::Class::TimeStamp->get_timestamp() - $dt;
$dm = $dy->minutes();
$dz = $dy->seconds();
@contArr = split("\n", $content);
$arraysz = @contArr;
$arraysz = $arraysz - 3;
$\="\n";
print($dm.':'.$dz.' with '.$arraysz.' Elements (JavaScript)');
E ora la parte triste. Questi sono i tempi che ottengo:
2:35 with 2 Elements (Erlang)
2:40 with 10000 Elements (Erlang)
2:38 with 30000 Elements (Erlang)
2:31 with 2 Elements (JavaScript)
2:40 with 10000 Elements (JavaScript)
2:51 with 30000 Elements (JavaScript)
btw questi sono minuti: secondi. Il numero è il numero di elementi restituiti dal filtro e il database contiene 90k Elementi. La grande sorpresa è stata che il filtro Erlang non era affatto più veloce.
Per richiedere tutti gli elementi richiede solo 9 secondi. E la creazione di viste su 15. Ma non è possibile per il mio uso su un telefono per trasferire tutti i documenti (motivi di volume e di sicurezza).
C'è un modo per filtrare su una vista per ottenere un aumento delle prestazioni? Oppure c'è qualcosa di sbagliato nelle mie funzioni di filtro di erlang (non sono sorpreso dai tempi dei filtri JavaScript).
MODIFICA: Come sottolineato da pgras, il motivo per cui questo è lento viene pubblicato nella risposta a this Domanda. Per fare in modo che i filtri di erlang girino più velocemente ho bisogno di fare un "livello" sotto e programmare l'erlang direttamente nel database e non come un documento _design. Ma non so davvero da dove cominciare e come farlo. Qualsiasi suggerimento sarebbe utile.
È possibile utilizzare _changes senza un parametro since, quindi verrà filtrato tutto il contenuto del DB, una volta la prima sincronizzazione hai intenzione di utilizzare il parametro since per le sincronizzazioni successive? Hai menzionato l'utilizzo di viste, sarebbe -fast- visualizzare con una chiave = "Fanta" risolvere i tuoi altri bisogni? – pgras
Voglio usare il filtro in seguito per replicare il database su un dispositivo mobile, ho usato la richiesta http solo per testare il filtro. Ho provato a utilizzare il filtro per una replica e ho ottenuto risultati simili. Non credo che una vista sarebbe d'aiuto perché in seguito si suppone che ci sia una query con il filtro. –
Passando attraverso la stessa cosa. Ho ottenuto un miglioramento del 55% quando uso Erlang per la replica filtrata, ma è ancora dolorosamente lento. – ryan1234