Domanda

Come vorresti affrontare il seguente problema di archiviazione e il recupero?

Circa 2.000.000 righe verranno aggiunti ogni giorno (365 giorni / anno) con le seguenti informazioni per riga:

  • id (identificatore di riga univoco)
  • ENTITY_ID (assume valori compresi tra 1 e 2.000.000 compreso)
  • date_id (incrementato con uno ogni giorno - assumerà valori compresi tra 1 e 3.650 (dieci anni: 1 * 365 * 10))
  • valore_1 (assume valori compresi tra 1 e 1.000.000 compreso)
  • valore_2 (assume valori compresi tra 1 e 1.000.000 compreso)

ENTITY_ID combinato con date_id è unico. Quindi, al massimo una riga per entità e quella può essere aggiunto alla tabella. Il database deve essere in grado di contenere 10 anni di valore di dati giornalieri (7.300.000.000 righe (3.650 * 2.000.000)).

Ciò che è descritto sopra è i modelli di scrittura. Il modello di lettura è semplice: tutte le query saranno effettuati su un ENTITY_ID specifica. Cioè recuperare tutte le righe che descrivono ENTITY_ID = 12345.

il supporto transazionale non è necessario, ma la soluzione di archiviazione deve essere open-source. Idealmente mi piacerebbe usare MySQL, ma sono aperto a suggerimenti.

Ora - come si dovrebbe affrontare il problema descritto

Aggiornamento: Mi è stato chiesto di elaborare per quanto riguarda la lettura e scrittura modelli. Scrive al tavolo sarà fatto in un unico lotto al giorno in cui saranno aggiunte le nuove voci 2M in un colpo solo. Letture sarà fatto in modo continuo con una sola lettura ogni secondo.

È stato utile?

Soluzione

partizionamento . Con il vostro modello di lettura che ci si vuole partizionare da entity_id hash.

Altri suggerimenti

"Ora - come è possibile affrontare il problema descritto"

Con semplici file flat.

Ecco perché

  

"tutte le query saranno effettuati su un   ENTITY_ID specifica. Cioè recuperare tutti   righe descrivono entity_id = 12345 ".

Hai 2.000.000 entità. Partizione in base al numero di entità:

level1= entity/10000
level2= (entity/100)%100
level3= entity%100

Il ciascun file dei dati è level1/level2/level3/batch_of_data

È possibile quindi leggere tutti i file in una determinata parte della directory di restituire i campioni per l'elaborazione.

Se qualcuno vuole un database relazionale, quindi caricare i file per un dato ENTITY_ID in un database per il loro uso.


Modifica On numeri al giorno.

  1. Il date_id / entity_id regola di unicità è non qualcosa che deve essere gestito. E '(a) banalmente imposto i nomi di file e (b) irrilevante per l'interrogazione.

  2. Il <=> "rollover" non significa nulla - non c'è domanda, quindi non c'è bisogno di rinominare nulla. Il <=> dovrebbe semplicemente crescere senza limite a partire dalla data epoca. Se si desidera eliminare i vecchi dati, quindi eliminare i vecchi file.

Dal momento che nessuna query si basa su <=>, nulla deve mai essere fatto con esso. Può essere il nome del file per tutto ciò che è importante.

Per includere il <=> nel set di risultati, scriverlo nel file con gli altri quattro attributi che sono in ogni riga del file.


Modifica in apertura / chiusura

Per la scrittura, è necessario lasciare il file (s) aperto. Tu fai vampate periodiche (o chiudere / riaprire) per assicurare che roba davvero sta andando a disco.

Avete due scelte per l'architettura del vostro scrittore.

  1. avere un unico processo di "scrittore" che consolida i dati dalle varie fonti (s). Ciò è utile se le query sono relativamente frequenti. Si paga per fondere i dati in fase di scrittura.

  2. avere diversi file aperti contemporaneamente per la scrittura. Quando l'esecuzione di query, unire questi file in un unico risultato. Questo è utile è query sono relativamente rari. Si paga per la fusione dei dati in fase di query.

Si potrebbe desiderare di guardare a queste domande:

Grande chiave primaria: 1+ miliardi di righe di MySQL + InnoDB

Grandi tabelle MySQL

Personalmente, mi piacerebbe anche che sul calcolo la larghezza di fila per dare un'idea di quanto grande la vostra tavola sarà (come da nota di partizionamento nel primo link).

HTH.,

S

L'applicazione sembra avere le stesse caratteristiche come la mia. Ho scritto un motore di storage personalizzata di MySQL per risolvere efficacemente il problema. E 'descritto qui

Imagine i dati sono disposti sul disco come un array di 2M voci lunghezza fissa (uno per ogni entità) ciascuno contenente 3650 righe (una per giorno) di 20 byte (la riga per un soggetto al giorno).

Il tuo modello read legge un'unica entità. Si è contiguo sul disco in modo che ci vuole 1 cercano (circa 8mllisecs) e leggere 3650x20 = circa 80K a forse 100 MB / sec ... così si è fatto in una frazione di secondo, facilmente soddisfare il secondo 1-query-per-leggere modello.

L'aggiornamento deve scrivere 20 byte di 2M luoghi diversi su disco. IN caso più semplice questo richiederebbe 2M cerca ognuna delle quali dura circa 8millisecs, quindi ci vorrebbe 2M * 8ms = 4,5 ore. Se si spalmano i dati attraverso 4 “RAID0” dischi potrebbe richiedere 1.125 ore.

Tuttavia, i posti sono solo 80K a parte. Nel che significa che ci sono 200 posti simili all'interno di un blocco 16 MB (dimensione tipica cache del disco) in modo che possano funzionare a qualsiasi fino a 200 volte più veloce. (1 minuto) La realtà è da qualche parte tra i due.

My motore di memorizzazione agisce su tale tipo di filosofia, anche se è un po scopo più generale di una matrice di lunghezza fissa.

Si potrebbe codice esattamente ciò che ho descritto. Mettere il codice in un motore di MySQL di stoccaggio pluggable significa che è possibile utilizzare MySQL per interrogare i dati con vari generatori di report, ecc.

A proposito, si potrebbe eliminare la data e l'ID entità dalla riga memorizzata (perché sono gli indici di matrice) e potrebbe essere l'ID univoco - se non si ha realmente bisogno in quanto (ID entità, data) è unico, e memorizzare i valori 2 come int 3 byte. Allora la vostra riga memorizzata è 6 byte, e si dispone di 700 aggiornamenti al 16M e quindi un'inserti più veloci e un file più piccolo.

Modifica Confronto di file flat

Ho notato che i file flat commenti favore generale. Non dimenticate che le directory sono solo indici attuate dal file system e sono generalmente ottimizzati per numero relativamente piccolo di relativamente grandi oggetti. Accesso ai file è generalmente ottimizzato in modo che prevede un numero relativamente piccolo di file ad aprirsi, e ha un relativamente elevato sovraccarico per aprire e chiudere, e per ogni file aperto. Tutti quelli "relativamente" sono relative all'utilizzo tipico di una banca dati.

Utilizzo dei nomi di file system come indice per un'entità-Id che ritengo essere un numero intero non-sparse 1 a 2Million è intuitivo. In una programmazione si usa un array, non un hash-table, per esempio, e si sta inevitabilmente andando a incorrere in una grande quantità di overhead per un percorso di accesso costoso che potrebbe essere semplicemente un'operazione indeing array.

Quindi, se si utilizzano file flat, perché non utilizzare semplicemente un file flat e indicizzarlo?

Modifica sul rendimento

Le prestazioni di questa applicazione sta per essere dominato da disco tempi di ricerca. I calcoli che ho fatto sopra determinano il meglio che si può fare (anche se è possibile rendere più veloce INSERT rallentando SELECT - non è possibile effettuare entrambi meglio). Non importa se si utilizza un database, flat-file o un file flat, eccezione che è possibile aggiungere più autore intende che non si ha realmente bisogno e rallentare ulteriormente verso il basso. Ad esempio, l'indicizzazione (se il suo l'indice del file system o di un indice di database) provoca I extra / O rispetto a "una matrice guardare in alto", e questi vi rallenterà.

Modifica su misurazioni di riferimento

Ho una tabella che assomiglia molto come la tua (o quasi esattamente come una delle partizioni). Era 64K entità non 2M (1/32 del vostro), e 2788 'giorni'. La tabella è stata creata nello stesso ordine INSERT che il vostro sarà, e ha lo stesso indice (ENTITY_ID, giorno). Un SELEZIONA su un organismo richiede 20,3 secondi per ispezionarei 2788 giorni, che è di circa 130 cerca per secondo come previsto (il giorno 8 millisecondi media cercano dischi di tempo). Il tempo SELEZIONA sarà proporzionale al numero di giorni, e non molto dipende dal numero di entità. (Sarà più veloce su dischi con cercare più velocemente i tempi. Sto usando un paio di SATA2s in RAID0, ma che non sta facendo molta differenza).

Se si ri-ordinare la tabella in ordine entità     ALTER TABLE x ORDER BY (entità, DAY) Poi lo stesso SELEZIONA richiederà 198 millisecs (perché sta leggendo l'entità ordine in un singolo accesso al disco). Tuttavia l'operazione di ALTER TABLE ha preso 13,98 giorni per completare (per 182m righe).

Ci sono alcune altre cose le misure che dicono 1. Il file di indice sta per essere grande come il file di dati. E '3GB per questa tabella di esempio. Ciò significa che (sul mio sistema) tutto l'indice a velocità del disco non velocità di memoria.

tasso di INSERT 2.Your diminuirà in modo logaritmico. L'inserto nel file di dati è lineare, ma l'inserimento della chiave nell'indice è log. A 180M record stavo ottenendo 153 INSERT al secondo, che è anche molto vicino al tasso di chiedere. Essa mostra che MySQL sta aggiornando un blocco indice di foglia per quasi ogni INSERT (come ci si aspetterebbe, perché è indicizzato sul soggetto, ma inserite in ordine giorno.). Quindi, siete alla ricerca di 2M / 153 sec = 3.6hrs per fare il vostro inserto quotidiano di righe 2M. (Diviso per qualunque effetto che si può ottenere da divisorio tra i sistemi o dischi).

simile problema (anche se con scala molto più grande - circa il vostro uso annuale ogni giorno)

Utilizzando un grande tavolo mi ha fatto stridere una battuta d'arresto - si può tirare un paio di mesi, ma credo che avrete finalmente suddiviso in partizioni.

Non dimenticate di indicizzare la tabella, altrimenti sarete scherzi con piccolo rivolo di dati ogni interrogazione; Oh, e se si vuole fare le query di massa, utilizzano file flat

La tua descrizione dei modelli di lettura non è sufficiente. Avrai bisogno di descrivere ciò che verranno recuperati quantità di dati, quanto spesso e quanto la deviazione ci saranno nelle query.

Questo vi permetterà di prendere in considerazione facendo la compressione su alcune delle colonne.

Guarda anche l'archiviazione e il partizionamento.

Se si desidera gestire i dati enorme con milioni di righe che può essere considerato simile a base di dati di serie temporali che registra il tempo e salva i dati nel database. Alcuni dei modi per memorizzare i dati sta usando InfluxDB e MongoDB.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top