È ipotizzabile avere milioni di liste di dati in memoria in Python?

4

Negli ultimi 30 giorni ho sviluppato un'applicazione Python che utilizza un database MySQL di informazioni (in particolare sugli indirizzi norvegesi) per eseguire la convalida e la correzione degli indirizzi. Il database contiene circa 2,1 milioni di righe (43 colonne) di dati e occupa 640 MB di spazio su disco.

Sto pensando alle ottimizzazioni della velocità e devo presumere che quando convalidi più di 10.000 indirizzi, ogni convalida esegue fino a 20 query al database, il networking è un collo di bottiglia di velocità.

Non ho ancora effettuato alcuna misurazione o tempismo, e sono sicuro che ci sono modi più semplici per ottimizzare l'applicazione della velocità al momento, ma voglio solo ottenere le opinioni degli esperti su quanto sia realistico caricare questo quantità di dati in una struttura riga-di-righe in Python. Inoltre, sarebbe anche più veloce? Sicuramente MySQL è ottimizzato per la ricerca di record tra una grande quantità di dati, quindi quanto aiuto sarebbe anche per rimuovere il passaggio di rete? Riesci a immaginare altri metodi validi per rimuovere il passaggio di rete?

La posizione del server MySQL varierà, poiché l'applicazione potrebbe essere eseguita da un laptop a casa o in ufficio, dove il server sarebbe locale.

    
posta Hubro 03.12.2012 - 10:48
fonte

3 risposte

3

Eviterei di caricare tutti i 2,1 milioni di righe in memoria (almeno, non sarebbe la mia prima scelta farlo). Anche se è possibile farlo con una query, e anche se si risolvono i problemi di memoria, ci vorrà ancora del tempo per ottenere tutti quei dati sul client. Le ricerche in questi dati potrebbero essere probabilmente più veloci di molte query SQL sulla rete, ma se ciò paga in realtà in confronto al caricamento iniziale è discutibile (ovviamente, dovrai misurarlo per essere sicuro).

Se ti ho capito bene, non hai bisogno di tutti quei dati per eseguire la convalida - hai bisogno solo di dati per ~ 10.000 indirizzi e un numero di record dal database di dimensioni comparabili. Probabilmente proverei a ridurre il numero di query per ottenere esattamente quei dati. Forse non hai bisogno di 20 query per indirizzo e puoi ridurlo a 10? Questo sarebbe un inizio. Forse puoi ottenere i dati per più indirizzi in una query anziché in molti, utilizzando gli operatori IN o OR nelle clausole WHERE delle tue istruzioni? Probabilmente questo sarebbe d'aiuto, dato che per una piccola quantità di dati, spesso il numero di query è il fattore chiave, non se ottieni 10, 100 o 1000 byte di risultati.

Se desideri consigli più specifici, devi fornire maggiori dettagli sul modello di dati e sulle query che stai utilizzando.

EDIT: si presume che il proprio database degli indirizzi sia stato congelato per diversi mesi, il che equivarrebbe a utilizzare una copia locale dell'intero database come cache. Qualcosa come SqlLite dovrebbe essere la scelta logica qui: un database molto veloce, senza server, in-process (e facoltativamente in memoria), in cui tutti i dati possono essere archiviati in un unico file. Puoi ancora usare SQL per tutte le query che ti servono, e la transizione dalle tabelle MySQL alle tabelle SqlLite dovrebbe essere semplice (a patto che tu non abbia usato troppo cose specifiche di MySQL nel tuo database attuale finora).

Considera che se stai cercando di mantenere la copia locale delle tue tabelle di db completamente in righe di righe Python, a seconda della complessità del modello di dati, probabilmente finirai per costruire qualcosa come il tuo "povero-uomo" "database in memoria per conto tuo. Allora, perché reinventare la ruota?

Informazioni sull'interfaccia Python SqlLite: link . Un altro vantaggio: se i dati dell'indirizzo vengono aggiornati sul server, questo approccio consente più o meno facilmente di creare una copia del database una volta sul server e di inviare i dati in un file sulla rete al client.

    
risposta data 03.12.2012 - 13:46
fonte
2

La risposta di Doc Brown e il commento di Mason Wheeler sono probabilmente i modi migliori e più pratici per andare qui. Detto questo, è un'interessante domanda concettuale, quindi sono propenso a commentare.

Also, would it even be any faster? Surely MySQL is optimized for looking up records among vast amounts of data, so how much help would it even be to remove the networking step?

Stiamo essenzialmente parlando di due cose: avere i dati lato client e avere "codice personalizzato" per effettuare le ricerche nel set di dati. I vantaggi che vedo per questo accordo:

  • Diminuzione del tempo di andata e ritorno ; con le prestazioni, dovresti misurare per essere sicuro di tutto, ma se si scopre che il tuo scenario è in gran parte dominato dall'attesa che 200.000 query vengano passate sulla rete (e viceversa), avere i dati sul client sarebbe sicuramente di aiuto. Dovresti anche scaricare il lavoro sul client, quindi questo potrebbe essere utile in uno scenario in cui ti aspetti molti client (ad esempio migliaia o più) allo stesso tempo.
  • Conoscenza approfondita dei dati e messa a punto delle strutture dati ; Il motore di MySQL è certamente molto ottimizzato, ma veramente non sa quali dati sta memorizzando (non gli importa se si tratta di indirizzi o numeri di telefono o informazioni sui pazienti). Puoi trarre vantaggio da questo fatto e trovare modi intelligenti per codificare le informazioni per una rapida ricerca. Per esempio. se sappiamo che la maggior parte delle strade norvegesi partono da un numero civico, e quindi sono per lo più contigue fino all'ultimo numero in quella strada, è possibile creare un meccanismo di ricerca piuttosto efficiente. Il numero civico è compreso tra il minimo e il massimo per quella strada e non nell'elenco delle eccezioni? Quindi è un indirizzo valido per quella strada. Per coincidenza, questo tipo di cose potrebbe essere fatto anche sul DB, la differenza principale sarebbe la possibilità di scegliere e sintonizzare le strutture di dati da soli (ad esempio con un algoritmo hash personalizzato, ecc.)

Il secondo punto potrebbe probabilmente essere usato per ottenere una rappresentazione più piccola del tuo DB. Non sono sicuro di quanto i tuoi dati siano normalizzati al momento, ma generalmente i DB tendono ad avere la maggior parte dell'indirizzo nel testo, che viene poi ripetuto molte volte più e più volte. Questo non è un modo molto efficiente di archiviare le cose, e se questo è vero per il tuo DB, potrebbe probabilmente essere rappresentato in un file molto più compatto (un test rapido potrebbe essere su ZIP o RAR sul DB per vedere se c'è molta duplicazione in anche se la distribuzione dei dati potrebbe significare che questi algoritmi non aiutano quanto potrebbero). A parte - se i numeri delle strade sono mescolati con i nomi delle strade come testo, suppongo che si possa fare molto per ottimizzare il DB per l'indicizzazione.

TL; DR: Sì, in teoria, potresti ottenere alcuni benefici dal trasferimento dei dati al lato client. In pratica, tuttavia, probabilmente stai molto meglio semplicemente limitando le tue query o utilizzando le altre grandi idee già pubblicate.

    
risposta data 04.12.2012 - 14:15
fonte
1

Si verificheranno dei problemi se si tenta di utilizzare gli elenchi Python per questo tipo di lavoro. Avrai un sovraccarico di memoria che probabilmente ti impedirà di fare qualcosa di utile con i tuoi dati.

Dovresti controllare Array ( link ) o se puoi numpy ( link ).

Se non riesci ancora a caricare tutti i tuoi dati nella memoria, puoi provare a elaborarli in blocchi per limitare il numero di query.

    
risposta data 03.12.2012 - 11:23
fonte

Leggi altre domande sui tag