Dividere le tabelle in MySQL. Buona pratica?


14

Ho iniziato a lavorare su un progetto esistente e lo sviluppatore precedente aveva suddiviso una tabella in 10 tabelle separate con schemi identici ma dati diversi.

I tavoli sono così:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

La chiave primaria è un idcampo intero . L'applicazione utilizza un algoritmo hash ( idmod 10) per sapere a quale tabella accedere durante le ricerche. Ad esempio id= 10 si tradurrebbe in [tableName_0].

Combinati, le tabelle hanno probabilmente 100.000 righe e il tasso di crescita è relativamente basso.

Quindi, la mia domanda è se questa è una soluzione praticabile o anche se è una buona pratica in qualsiasi situazione. La mia teoria è quella di spingerli a combinarli in quanto renderà le cose più facili per quanto riguarda UNIONs, ecc. L'aspetto negativo principale sta cambiando tutto il codice dell'applicazione e se ne vale la pena nel lungo periodo.

Risposte:


16

Penso che tutti lo stiano complicando troppo. Il punto chiave qui è:

Combinati, le tabelle hanno probabilmente 100.000 righe e il tasso di crescita è relativamente basso.

Questo è un gioco da ragazzi per qualsiasi RDBMS da gestire. Scegli una tabella, indicizzala correttamente e considerala un problema risolto.

Non è necessario prendere in considerazione il partizionamento, sia "fatto in casa" o meno, fino a quando non si inizia a gestire volumi di dati estremamente grandi - si pensi a miliardi di righe e oltre.


3

È possibile utilizzare le tabelle di unione, tuttavia sono più antiquate rispetto alle versioni 4.x. Dato che la tua applicazione viene partizionata manualmente in quanto è a) stai eseguendo una versione davvero vecchia oppure b) lo sviluppatore originale non era a conoscenza delle partizioni di tabella.

In breve, se stai eseguendo 5.1+, puoi lasciare che mysql faccia questo partizionamento per te. Vedi http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Se stai usando 5.5 dovresti controllare quei documenti specifici poiché troverai alcune differenze.

I vantaggi del partizionamento sono numerosi. Tuttavia, dipende davvero dal set di dati a portata di mano, dai modelli di accesso e da come deve essere indicizzato. Inoltre, tieni presente che i miei commenti seguenti sono nel contesto del partizionamento mysql 5+, NON delle tabelle Merge mysql precedenti; anche se a volte sono discussi in termini di partizioni.

Qualche esempio:

  • Bucketing diretto (o hashing) basato sulla chiave di ricerca a cui si accede frequentemente. Se stai quasi sempre cercando una chiave primaria o unica, allora mysql può tagliare lo spazio di ricerca in base al numero di partizioni che hai. Nota, tuttavia, ciò può essere dannoso se esegui la partizione in base a una chiave e successivamente esegui una ricerca frequente in un'altra chiave. Se cerchi per chiave i dati non sono partizionati, allora deve fare PIÙ ricerche nelle ricerche (una per ogni partizione, b / c francamente, non sa dove siano i dati)
  • Considera le situazioni in cui hai una serie temporale di record che cresce per data e periodicamente elimini il mese precedente. Se esegui il partizionamento per data, puoi semplicemente rilasciare una partizione che è altrettanto veloce di rilasciare una tabella, non importa quanto sia grande. Se dovessi eliminare una tabella del genere in base alle date, dovresti emettere una o più query DELETE in cui viene eliminata ogni singola riga. L'aspetto negativo di questo è che mysql non crea automaticamente nuove partizioni una volta raggiunta la data massima che hai rappresentato in questo scenario; hai bisogno di script di manutenzione extra creati da te per aggiungere le partizioni quando sono necessarie.
  • Se stai usando i controlli myisam e i recuperi sono molto più veloci. Prendi in considerazione una tabella myisam 100G. Se si desidera ripristinare una tabella bloccata, sono necessari almeno 100 G di spazio libero su disco. Se fosse partizionato in 10 diversi blocchi di uguale dimensione, allora avrai bisogno solo di 10 G di spazio (e meno memoria key_sort_buffer per un rapido recupero); ma avrebbe bisogno di fare un'iterazione per ogni partizione.

Quindi, in sintesi, l'approccio generale delle tabelle di partizionamento può offrire molti vantaggi. Tuttavia non è un proiettile magico da applicare alla cieca senza considerare gli schemi di accesso e il modo in cui esattamente stai partizionando.

Potrei immaginare situazioni in cui il partizionamento desiderato è molto specifico per l'applicazione e sarebbe più adatto ad avere quella logica nel livello dell'applicazione. Tuttavia, data la descrizione del modulo 10 diretto, questo non sembra un caso del genere.

MODIFICARE

Nel scrivere la mia descrizione ho dimenticato che hai dichiarato che la tua tabella è di 100.000 righe. Senza lo schema completo della tabella e la lunghezza media delle righe è difficile da dire con certezza, ma in generale suona di medie dimensioni anche per hardware modesto. Allo stesso tempo, se non sta causando problemi così come sono adesso o nel prossimo futuro, non perdere tempo e introdurre rischi cambiandoli.


3

Ciò che lo sviluppatore precedente ha fatto per te è stata la propria implementazione della partizione per hash. MySQL lo supporta letteralmente da MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

Non riesco a pensare a una buona ragione, quindi implementa la tua partizione per hash anziché fare affidamento sulla versione nativa [1]. L'esecuzione delle modifiche allo schema sarà un incubo.

Inoltre raramente raccomando partizione per hash (l'implementazione nativa). Penso che sarebbe utile se potessi usarlo per cercare in parallelo ciascuna delle partizioni contemporaneamente (cosa che MySQL non farà). Se devi cercare tra più partizioni, lo schema che hai descritto sarà spesso molto più lento.

[1] Tuttavia, per alcuni degli altri tipi di partizionamento può essere opportuno eseguire il rollup del proprio partizionamento. MySQL ti obbliga a rendere la chiave di partizione parte della tua chiave primaria e di tutti gli indici univoci.


2

In risposta alla domanda:

è se questa è una soluzione praticabile

IMHO, questo sembra un sovraccarico inutile. Puoi semplicemente indicizzare e partizionare correttamente una singola tabella a meno che non ci siano altre informazioni non rivelate nella descrizione.

In risposta alla domanda:

... se è una buona pratica in qualsiasi situazione

IMHO, lo sharding verticale può avere senso a seconda del contesto. Quando vedo questo, è in genere in una sorta di forma di registro. Facciamo finta di usarlo per i log del web server e vogliamo partizionare per mese. Invece di modificare una tabella esistente ogni giorno, potremmo creare una nuova tabella ogni giorno e registrare le righe su quella tabella.

ad esempio, fingere che una tabella dei registri web possa assumere la forma:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

La soluzione crea tabelle in base alle esigenze nel database del weblog:

weblogs.20120301
weblogs.20120302
weblogs.20120303

eccetera.

In questo modo, i dati rimangono gestibili e ricercabili. L'estrazione diventa un normale processo periodico. Le operazioni continue non vengono bloccate da operazioni su dati meno recenti.

Nello scenario che hai presentato sei comunque bloccato in una struttura, quindi perché non utilizzare una singola tabella ottimizzata per questo scopo? La memorizzazione di righe basata su algoritmo sembra abbozzata e soggetta a errori.


0

Se una query ha come target dati enormi, la suddivisione dei dati in base alle condizioni della query avrebbe un notevole miglioramento delle prestazioni. Ma tale suddivisione, come hai visto, fa emergere alcuni problemi di programmazione.

Quindi la domanda è: vale la pena spaccare per la performance o danneggiare la performance?

Se si dispone di una transazione che deve bloccare più righe su più tabelle e presenta problemi (ad esempio deadlock o timeout della transazione), è possibile combinarli in un'unica tabella e riscrivere l'SQL per risolvere i problemi.

Quando penso a dividere la tabella, consideravo il compromesso tra guadagno delle prestazioni e complessità della programmazione.

Nella tua situazione, la modifica del codice esistente potrebbe essere una soluzione a lungo termine per facilitare la manutenzione del codice. Suggerirei un tentativo di meta-programmazione. Ad esempio, utilizzando StringTemplate per generare SQL in modo dinamico. Mi piace generare SQL dal motore di meta-programmazione se la modifica del codice esistente è troppo difficile.


0

Quando è necessario archiviare i file nella tabella, utilizzare questa metodologia aiuta a esportare, riparare e ripristinare.

Ho tabelle con> 30 GB partizionate in 10 tabelle. Queste tabelle hanno solo ID - BLOB e per me è facile da conservare. E utilizzo MyISAM per salvare il buffer INNODB.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.