it-swarm-eu.dev

Jak odstraníte fragmentaci z tabulek InnoDB?

Mám databázi mající počet tabulek.

Chci odstranit některé záznamy z tabulek, že počet záznamů není větší než 20 kB nebo 50 kB.

Všechny tabulky jsou InnoDB. A file_per_table je vypnuto.

Když odstraním záznamy z několika tabulek, bude v tabulkách fragmentace.

Existuje nějaký způsob, jak fragmentaci odstranit??

Aktualizace 17. dubna

mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME      | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City            | world_innodb |   5242880 |
| City_Copy       | world_innodb |   5242880 |
| Country         | world_innodb |   5242880 |
| CountryLanguage | world_innodb |   5242880 |
| a               | world_innodb |   5242880 |
| t1              | world_innodb |   5242880 |
| t2              | world_innodb |   5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)

Takže teď moje otázka zní, jak se rozhodnu, že moje tabulky jsou roztříštěné nebo ne.

13
Abdul Manaf

Tuto otázku jsem už v říjnu 2010 adresoval v StackOverflow .

Nezapomeňte na nejrušnější soubor v infrastruktuře InnoDB:/var/lib/mysql/ibdata1

Tento soubor obvykle obsahuje čtyři typy informací

  • Data tabulky
  • Indexy tabulky
  • Data MVCC (Multiversioning Concurrency Control)
  • Metadata tabulky (seznam ID tabulkového prostoru)

Běh OPTIMIZE TABLE proti tabulce InnoDB uložené v ibdata1 dělá dvě věci:

  • Zpřístupňuje data a indexy tabulky uvnitř ibdata1, takže je přístup rychlejší
  • To způsobí, že ibdata1 roste, protože souvislá data a indexové stránky jsou připojeny k ibdata1

I když můžete oddělit tabulková data a indexy tabulek od ibdata1 a spravovat je samostatně pomocí innodb_file_per_table , velká mezera celého diskového prostoru v ibdata1 jednoduše nezmizí a nelze jej získat zpět. Musíte udělat víc.

Chcete-li zmenšit ibdata1 jednou provždy, musíte provést následující:

1) MySQLDump všechny databáze do textového souboru SQL (volejte to /root/SQLData.sql)

2) Vypusťte všechny databáze (kromě schématu mysql)

3) Vypnutí mysql

4) Do souboru /etc/my.cnf přidejte následující řádky

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Sidenote: Ať už je váš soubor innodb_buffer_pool_size jakýkoli, ujistěte se, že innodb_log_file_size je 25% innodb_buffer_pool_size.

5) Odstraňte ibdata1, ib_logfile0 a ib_logfile1

V tomto okamžiku by mělo být v adresáři/var/lib/mysql pouze schéma mysql

6) Restartujte mysql

Tím se znovu vytvoří ibdata1 při 10 nebo 18 MB (v závislosti na verzi MySQL), ib_logfile0 a ib_logfile1 po 1G

7) Znovu načtěte /root/SQLData.sql do mysql

ibdata1 poroste, ale obsahuje pouze tabulková metadata. Ve skutečnosti v průběhu let poroste velmi pomalu. Jediným způsobem, jak rychle růst ibdata1, je, pokud máte jednu nebo více z následujících možností:

  • Mnoho DDL (CREATE TABLE, DROP TABLE, ALTER TABLE)
  • Mnoho transakcí
  • Mnoho změn, které je třeba provést pro jednu transakci

Každá tabulka InnoDB bude existovat mimo ibdata1

Předpokládejme, že máte tabulku InnoDB s názvem mydb.mytable. Pokud jdete do/var/lib/mysql/mydb, uvidíte dva soubory představující tabulku

  • mytable.frm (záhlaví Storage Engine)
  • mytable.ibd (Data dat tabulky a indexy tabulek pro mydb.mytable)

ibdata1 už nikdy nebude obsahovat data InnoDB a indexy.

S volbou innodb_file_per_table v /etc/my.cnf můžete spustit OPTIMIZE TABLE mydb.mytable; a soubor /var/lib/mysql/mydb/mytable.ibd se skutečně zmenší.

Ve své kariéře jsem to udělal mnohokrát jako MySQL DBA

Ve skutečnosti, když jsem to udělal poprvé, sbalil jsem 50GB ibdata1 soubor na 500 MB.

Pokusit se. Máte-li k tomu další dotazy, napište mi. Věř mi. To bude fungovat v krátkodobém horizontu a po dlouhé vzdálenosti !!!

AKTUALIZACE 2012-04-19 09:23 EDT

Jak můžete po provedení výše uvedených kroků zjistit, které tabulky je třeba defragmentovat? Je možné to zjistit, ale budete to mít skript.

Zde je příklad: Předpokládejme, že máte tabulku mydb.mytable. Se zapnutou innodb_file_per_table máte soubor /var/lib/mysql/mydb/mytable.ibd

Budete muset získat dvě čísla

FILESIZE from OS: Můžete zjistit velikost souboru z OS takto

ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'

FILESIZE FROM INFORMATION_SCHEMA: Velikost souboru můžete zjistit z information_schema.tables takto:

SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

Stačí odečíst hodnotu INFORMATION_SCHEMA od hodnoty OS a rozdíl vydělit hodnotou INFORMATION_SCHEMA.

Odtud byste se rozhodli, jaké procento považuje za nutné defragmentovat tuto tabulku. Samozřejmě je defragujete pomocí jednoho z následujících příkazů:

OPTIMIZE TABLE mydb.mytable;

nebo

ALTER TABLE mydb.mytable ENGINE=InnoDB;
14
RolandoMySQLDBA

Pokud často odstraňujete řádky (nebo aktualizujete řádky s datovými typy s proměnnou délkou), můžete skončit s velkým množstvím zbytečného místa v datových souborech, podobně jako fragmentace souborového systému.

Pokud nepoužíváte innodb_file_per_table možnost, jediné, co s tím můžete udělat, je export a import databáze, časově a diskově náročná procedura.

Ale pokud používáte innodb_file_per_table, můžete tento prostor identifikovat a získat zpět!

Před 5.1.21 je čítač volného místa k dispozici ve sloupci table_comment v information_schema.tables. Zde je několik SQL pro identifikaci tabulek s nejméně 100M (ve skutečnosti 97,65M) volného místa:

VÝBĚR table_schema, table_name, table_comment FROM
information_schema.tables WHERE ENGINE LIKE 'InnoDB' A table_comment RLIKE 'InnoDB free: ([0-9] {6,}). *';

Počínaje 5.1.21 bylo toto přesunuto do sloupce data_free (mnohem vhodnější místo):

VÝBĚR table_schema, table_name, data_free/1024/1024 AS data_free_MB FROM information_schema.tables WHERE ENGINE LIKE 'InnoDB' AND data_free> 100 * 1024 * 1024;

Ztracený prostor můžete získat opětovným vytvořením tabulky. Nejlepší způsob, jak toho dosáhnout, je použití „alternativní tabulky“, aniž by se ve skutečnosti nic změnilo:

ALTER TABLE `TableName` ENGINE=InnoDB;

To je to, co MySQL dělá v zákulisí, pokud spustíte „optimalizaci tabulky“ v tabulce InnoDB. Výsledkem bude zámek pro čtení, ale nikoli zámek celého stolu. Jak dlouho to trvá, je zcela závislé na množství dat v tabulce (ale ne na velikosti datového souboru). Pokud máte tabulku s velkým množstvím vymazání nebo aktualizací, možná budete chtít spustit tento měsíc nebo dokonce týdně.

5
Mahesh Patil