Mam tabelę InnoDB o pojemności 700 GB, do której nie zapisuję już żadnych danych (tylko czytam). Chciałbym usunąć starsze przechowywane w nim dane i odzyskać to miejsce na dysku (gdy mi się kończy). Usunięcie części jest dość łatwe, ponieważ mam indeks główny auto-inc, dzięki czemu mogę po prostu iterować fragmenty, używając go i usuwać wiersze, ale to nie przywróci mi miejsca. Zakładam, że OPTIMIZE TABLE
tak, ale może to potrwać wiecznie na stole o pojemności 700 GB, więc czy jest inna opcja, którą przeoczam?
Edytuj przez RolandoMySQLDBA
Zakładając, że twoja tabela jest mydb.mytable
, uruchom następującą kwerendę i opublikuj ją tutaj, aby określić miejsce na dysku potrzebne do zmniejszenia tabeli:
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;
Musimy także zobaczyć strukturę tabeli, jeśli jest to dozwolone.
Edytuj przez Noam
To jest wynik zapytania:
datsize ndxsize tblsize
682,51 47,57 730.08
To jest struktura tabeli ( 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`
ALTER TABLE ... ENGINE=InnoDB;
(jeśli masz na to miejsce). Większość jest zadowolona ze swoich bardzo szybkich dysków SSD i nie będzie się już martwić.Odpowiedzi:
To dobre pytanie. Masz kilka rozwiązań, ale twój stół jest dość duży, więc żadne nie będzie bez bólu :)
Masz trzy rozwiązania do „zmniejszania” tabel InnoDB:
1. OPTYMALIZUJ TABELĘ
Możesz używać
OPTIMIZE TABLE
tak jak wspomniałeś, ale powinieneś dbać oinnodb_file_per_table
zmienną:Pozwól mi wyjaśnić:
Za pomocą
OPTIMIZE TABLE
tabel InnoDB blokuje się tabelę, kopiuje dane do nowej czystej tabeli (dlatego wynik jest pomniejszony), upuszcza oryginalną tabelę i zmienia nazwę nowej tabeli z oryginalną nazwą. Dlatego powinieneś zadbać o to, aby podwoić wolumetrię swojego stołu dostępną na dysku (podczas pracy potrzebujesz 2x700 GB).Gdy jesteś w innodb_file_per_table = ON. Wszystkie tabele mają odpowiedni plik danych. Więc…
OPTIMIZE
instrukcja utworzy nowy plik danych (~ 700 GB) po zakończeniu operacji, MySQL usunie oryginalny plik i zmieni nazwę nowego (więc na koniec 700 GB - prawdopodobnie mniej, ponieważ zostanie zmniejszone - danych) wygenerowane podczas operacji zostaną zwolnione)Gdy jesteś w pliku innodb_file_per_table = OFF. Wszystkie dane trafiają do jednego pliku danych: ibdata . Ten plik ma smutną cechę, nie można go zmniejszyć. Tak więc w trakcie
OPTIMIZE
procesu tworzona jest nowa tabela (blisko 700 GB), ale nawet po operacji upuszczania i zmiany nazwy (i na końcuOPTIMIZE
fazy) twoja ibdata nie zwolni ~ ~ 700 GB, więc chciałeś zwolnić trochę danych, ale masz 700 GB więcej, spoko, prawda?2. ZMIEŃ TABELĘ
Możesz także użyć
ALTER TABLE
instrukcji,ALTER TABLE
będzie działać w taki sam sposób jakOPTIMIZE TABLE
. Możesz po prostu użyć:3. ALTER TABLE (ONLINE)
Problem
OPTIMIZE
iALTER TABLE
że blokuje tabeli podczas pracy. Możesz użyć narzędzia Percona: pt-online-schema-change (z Percona Toolkit: link ). pt-online-schema ... zbuduje mechanizm z wyzwalaczami i tabelą tymczasową, które pozwolą, aby oryginalna tabela była dostępna do odczytu i zapisu podczas operacji. Używam tego narzędzia w produkcji,ALTER
ponieważ jest całkiem fajne.Pamiętaj, że powinieneś
FOREIGN KEY
odwoływać się do tabeli, FK i powoduje ryzyko wywołania bałaganu. Aby sprawdzić te wymagania wstępne, zapytaj:Oto jak używam zmiany pt-online-schemat:
Zauważ, że moja uwaga na temat innodb_file_per_table jest prawdziwa także dla tego rozwiązania.
4. mysqldump
Ostatnim rozwiązaniem jest odtworzenie wszystkich baz danych ze zrzutu. Strasznie długie, ale strasznie wydajne. Pamiętaj, że jest to jedyne rozwiązanie, aby „zmniejszyć” plik ibdata.
Max.
źródło
Jeśli masz mało miejsca na dysku, sugeruję, abyś zrobił to tak, jak Max sugerował przy zmianie pt-online-schemat-zmiana (ONLINE). Byłem w tej samej sytuacji ze znacznie mniejszym stołem (200 GB) i zdecydowałem się na kompresję w tym samym czasie. Coś w tym stylu powinno działać:
Działa to tylko wtedy, gdy masz format pliku barracuda i format tabeli COMPACT. Musisz także mieć włączoną opcję innodb_file_per_table. Może to robić cuda na podstawie wielkości tabeli, szczególnie jeśli jest dużo tekstu i jeśli używasz mniejszego KEY_BLOCK_SIZE, takiego jak 8K lub nawet 4K (domyślnie 16K). Możesz także sprawdzić, ile miejsca możesz zyskać na wielu testach porównawczych dotyczących tego problemu na innych blogach, ale dokumentacja MySQL reklamuje od 25% do 50% (dla mnie było to prawie 90%).
Zauważ, że może to również wpłynąć na wydajność podczas wykonywania SELECT (z dokumentacji MySQL):
MySQL musi również rozpakować dane, gdy nie znajduje się w puli buforów. Więc bądźcie ostrzeżeni.
To naprawdę działało dobrze w moim przypadku. Miałem długi tekst. 200 GB stało się 26 GB. Występy nie uległy zmianie.
Aby uzyskać więcej szczegółowych informacji, sprawdź te linki:
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
źródło