Eliminazione e recupero dello spazio dalla tabella InnoDB


14

Ho una tabella InnoDB da 700 GB a cui non sto scrivendo altri dati (solo lettura). Vorrei eliminare i dati più vecchi in suo possesso e recuperare lo spazio su disco (mentre lo sto esaurendo). La parte di eliminazione è piuttosto semplice, perché ho un indice primario auto-inc, quindi posso solo iterare in blocchi usando esso, ed eliminare le righe, ma questo non mi restituirà lo spazio. Suppongo che lo OPTIMIZE TABLEfarà, ma che potrebbe richiedere un'eternità su un tavolo da 700 GB, quindi c'è un'altra opzione che sto trascurando?

Modifica di RolandoMySQLDBA

Supponendo che la tabella sia mydb.mytable, eseguire la query seguente e pubblicarla qui in modo da poter determinare lo spazio su disco necessario per la riduzione della tabella:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

Dobbiamo anche vedere la struttura della tabella, se consentita.

Modifica di Noam

Questo è l'output della query:

datsize ndxsize tblsize
682.51 47.57 730.08

Questa è la struttura della tabella ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

Hai un altro volume del disco per catturare solo i dati ???
RolandoMySQLDBA

@RolandoMySQLDBA Ho un disco rigido esterno che posso montare. Questo conta?
Noam,

@RolandoMySQLDBA ma ovviamente piacerebbe un'opzione per eliminare un po 'di spazio senza la necessità di avere altri 700 GB
Noam

@RolandoMySQLDBA la dimensione del disco aggiuntiva causa problemi di prestazioni?
Aris,

@Aris potrebbe dipendere dal disco e dal suo tempo di ricerca. Al giorno d'oggi, la maggior parte dei dischi ora funziona meglio, ma a che serve sprecare i cicli (anche andando molto velocemente) se si hanno grandi tasche sparse di spazio su disco nella tabella ???. Ciò è particolarmente vero per InnoDB che è normalmente fissato a blocchi di 16 KB. Con la frammentazione interna di blocchi da 16 KB, potresti voler deframmentare la tabella usando ALTER TABLE ... ENGINE=InnoDB;(se hai la stanza per farlo). Molti sono semplicemente soddisfatti dei loro SSD molto veloci e non si preoccupano più.
RolandoMySQLDBA

Risposte:


21

Questa è una buona domanda Hai diverse soluzioni ma il tuo tavolo è abbastanza grande, quindi nessuno sarà senza dolore :)

Sono disponibili tre soluzioni per "ridurre" le tabelle InnoDB:

1. TABELLA OTTIMIZZATA

Puoi usarlo OPTIMIZE TABLEcome hai detto, ma dovresti preoccuparti della innodb_file_per_tablevariabile:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Lasciatemi spiegare:

Con le OPTIMIZE TABLEtabelle InnoDB, blocca la tabella, copia i dati in una nuova tabella pulita (motivo per cui il risultato viene ridotto), elimina la tabella originale e rinomina la nuova tabella con il nome originale. Ecco perché dovresti preoccuparti di avere il doppio della volumetria della tua tabella disponibile sul tuo disco (Durante il funzionamento avrai bisogno di 2x700GB).

Quando sei in innodb_file_per_table = ON. Tutte le tabelle hanno il proprio file di dati. Quindi la OPTIMIZEdichiarazione creerà un nuovo file di dati (~ 700 GB) al termine dell'operazione, MySQL lascerà cadere quello originale e rinominerà quello nuovo (quindi alla fine i 700 GB - probabilmente meno perché saranno ridotti - di dati generato durante l'operazione verrà rilasciato)

Quando sei in innodb_file_per_table = OFF. Tutti i dati vanno in un unico file di dati: ibdata . Questo file ha una triste particolarità, non può essere ridotto. Quindi durante il OPTIMIZEprocesso, la tua nuova tabella verrà creata (vicino a 700 GB), ma anche dopo l'operazione di rilascio e ridenominazione (e la fine della OPTIMIZEfase) il tuo ibdata non rilascerà i ~ 700 GB, quindi volevi liberare dei dati ma hai 700 GB di più, figo vero?

2. ALTER TABLE

Puoi anche usare ALTER TABLEun'istruzione, ALTER TABLEfunzionerà allo stesso modo di OPTIMIZE TABLE. Puoi semplicemente usare:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLE (ONLINE)

Il problema di OPTIMIZEe ALTER TABLEche blocca la tabella durante il funzionamento. Puoi usare lo strumento Percona: pt-online-schema-change (da Percona Toolkit: link ). pt-online-schema ... costruirà un meccanismo con trigger e tabella temporanea che consentono alla tabella originale di essere disponibile per la lettura e la scrittura durante l'operazione. Uso questo strumento in produzione per i grandi ALTER, è piuttosto bello.

Nota che avresti dovuto fare FOREIGN KEYriferimento alla tabella, all'FK e ai rischi innescati per produrre un pasticcio. Per verificare questi prerequisiti, eseguire una query:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

Ecco come utilizzo pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Nota che la mia nota su innodb_file_per_table è vera anche per questa soluzione.

4. mysqldump

L'ultima soluzione è ricreare tutti i database da un dump. Terribilmente lungo, ma terribilmente efficiente. Si noti che è l'unica soluzione per "ridurre" il file ibdata.

Max.


Anche nell'opzione di alter table online dello strumento percona avrò bisogno di 700 GB di spazio libero su disco?
Noam,

Sì, pt-online usa solo un po 'di meccanismo per fare l'ALTER online ma fa comunque un ALTER.
Maxime Fouilleul,

@MaximeFouilleul la dimensione del disco aggiuntiva causa problemi di prestazioni?
Aris,

1

Se sei a corto di dimensioni del disco, ti suggerisco di fare proprio come suggerito da Max con pt-online-schema-change (ONLINE). Sono stato nella stessa situazione con un tavolo molto più piccolo (200 GB) e ho scelto di fare un po 'di compressione allo stesso tempo. Qualcosa del genere dovrebbe funzionare:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Funzionerà solo se sei nel formato file barracuda e nel formato COMPACT della tabella. Inoltre devi avere innodb_file_per_table abilitato. Questo può fare meraviglie sulla dimensione della tua tabella soprattutto se c'è molto testo e se usi KEY_BLOCK_SIZE più piccoli come 8K o addirittura 4K (il valore predefinito è 16K). Puoi anche verificare quanto spazio puoi guadagnare da più benchmark su questo problema su altri blog, ma la documentazione di MySQL pubblicizza dal 25% al ​​50% (era quasi il 90% per me).

Si noti che ciò può influire anche sulle prestazioni quando si eseguono i SELECT (dalla documentazione di MySQL):

Pertanto, in qualsiasi momento, il pool di buffer potrebbe contenere sia la forma compressa che non compressa della pagina, oppure solo la forma compressa della pagina, o nessuna delle due.

MySQL deve anche decomprimere i dati quando non si trovano nel pool di buffer. Quindi attenzione.

Nel mio caso ha funzionato davvero bene. Ho avuto un lungo messaggio. 200 GB sono diventati 26 GB. Gli spettacoli non sono stati modificati.

Per informazioni più approfondite controlla questi link:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

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.