Mam bazę danych o liczbie tabel.
Chcę usunąć niektóre rekordy z tabel, które mówią, że liczba rekordów jest większa niż 20 000 lub 50 000.
Wszystkie tabele są InnoDB. I file_per_table
jest wyłączony .
Kiedy usunę rekordy z wielu tabel, nastąpi ich fragmentacja.
Czy istnieje sposób na usunięcie fragmentacji.
Aktualizacja 17 kwietnia
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)
Więc teraz moje pytanie brzmi: w jaki sposób zdecyduję, że moje tabele są pofragmentowane, czy nie.
Odpowiedzi:
Rozwiązałem to w StackOverflow w październiku 2010 roku .
Pamiętaj o najbardziej zajętym pliku w infrastrukturze InnoDB: / var / lib / mysql / ibdata1
Ten plik zwykle zawiera cztery rodzaje informacji
Uruchamianie
OPTIMIZE TABLE
z tabelą InnoDB przechowywaną w ibdata1 ma dwie rzeczy:Podczas gdy możesz segregować dane tabel i indeksy tabel od ibdata1 i zarządzać nimi niezależnie za pomocą innodb_file_per_table , duża rozbieżność całego miejsca na dysku w ibdata1 po prostu nie zniknie i nie będzie można go odzyskać. Musisz zrobić więcej.
Aby raz na zawsze zmniejszyć ibdata1 , wykonaj następujące czynności:
1) MySQL Zrzuć wszystkie bazy danych do pliku tekstowego SQL (nazwij go /root/SQLData.sql)
2) Usuń wszystkie bazy danych (oprócz schematu mysql)
3) Zamknij mysql
4) Dodaj następujące wiersze do /etc/my.cnf
Uwaga: Niezależnie od tego, jaki zestaw masz dla innodb_buffer_pool_size, upewnij się, że innodb_log_file_size to 25% innodb_buffer_pool_size.
5) Usuń ibdata1, ib_logfile0 i ib_logfile1
W tym momencie powinien istnieć tylko schemat mysql w katalogu / var / lib / mysql
6) Uruchom ponownie mysql
Spowoduje to ponowne utworzenie ibdata1 przy 10 lub 18 MB (w zależności od wersji MySQL), ib_logfile0 i ib_logfile1 przy 1G każdy
7) Ponownie załaduj /root/SQLData.sql do mysql
ibdata1 wzrośnie, ale będzie zawierał tylko metadane tabeli. W rzeczywistości będzie rosła bardzo powoli z biegiem lat. Jedynym sposobem szybkiego wzrostu ibdata1 jest posiadanie jednego lub więcej z poniższych:
CREATE TABLE
,DROP TABLE
,ALTER TABLE
)Każda tabela InnoDB będzie istniała poza ibdata1
Załóżmy, że masz tabelę InnoDB o nazwie mydb.mytable. Jeśli przejdziesz do / var / lib / mysql / mydb, zobaczysz dwa pliki reprezentujące tabelę
ibdata1 nigdy nie będzie już zawierał danych i indeksów InnoDB.
Dzięki opcji innodb_file_per_table w /etc/my.cnf można uruchomić,
OPTIMIZE TABLE mydb.mytable;
a plik /var/lib/mysql/mydb/mytable.ibd faktycznie się zmniejszy.Robiłem to wiele razy w mojej karierze jako MySQL DBA
W rzeczywistości, kiedy pierwszy raz to zrobiłem, zwinąłem 50 GB pliku ibdata1 do 500 MB.
Spróbuj. Jeśli masz dodatkowe pytania, napisz do mnie. Zaufaj mi. Będzie to działać w krótkim okresie i na dłuższą metę !!!
AKTUALIZACJA 2012-04-19 09:23 EDT
Po uruchomieniu powyższych kroków, w jaki sposób można ustalić, które tabele należy poddać defragmentacji? Można się dowiedzieć, ale będziesz miał skrypt.
Oto przykład: Załóżmy, że masz tabelę
mydb.mytable
. Po włączeniu innodb_file_per_table masz plik /var/lib/mysql/mydb/mytable.ibdBędziesz musiał pobrać dwie liczby
FILESIZE FROM OS: Możesz sprawdzić rozmiar pliku w systemie operacyjnym w ten sposób
FILESIZE FROM INFORMATION_SCHEMA: Możesz sprawdzić rozmiar pliku z Information_schema.tables w następujący sposób:
Wystarczy odjąć wartość INFORMACJE_SCHEMA od wartości OS i podzielić różnicę przez wartość INFORMACJA_SCHEMA.
Następnie zdecydujesz, jaki procent uważa za konieczne defragmentację tej tabeli. Oczywiście defragmentujesz go za pomocą jednego z następujących poleceń:
lub
źródło
Jeśli często usuwasz wiersze (lub aktualizujesz wiersze o typach danych o zmiennej długości), możesz skończyć z dużą ilością zmarnowanego miejsca w plikach danych, podobnie jak fragmentacja systemu plików.
Jeśli nie korzystasz z tej
innodb_file_per_table
opcji, jedyne, co możesz z tym zrobić, to wyeksportować i zaimportować bazę danych, co jest procedurą wymagającą dużo czasu i miejsca na dysku.Ale jeśli używasz
innodb_file_per_table
, możesz zidentyfikować i odzyskać to miejsce!Przed 5.1.21 licznik wolnego miejsca jest dostępny w kolumnie table_comment w pliku information_schema.tables. Oto kilka instrukcji SQL służących do identyfikacji tabel z co najmniej 100 mln (faktycznie 97,65 mln) wolnego miejsca:
Począwszy od 5.1.21 przeniesiono to do kolumny data_free (o wiele bardziej odpowiednie miejsce):
Możesz odzyskać utracone miejsce, odbudowując stół. Najlepszym sposobem na to jest użycie „alter table” bez faktycznej zmiany:
To właśnie robi MySQL za kulisami, jeśli uruchomisz „optymalizację tabeli” na tabeli InnoDB. Spowoduje to blokadę odczytu, ale nie blokadę pełnego stołu. To, jak długo to zajmie, zależy całkowicie od ilości danych w tabeli (ale nie od wielkości pliku danych). Jeśli masz tabelę z dużą liczbą operacji usuwania lub aktualizacji, możesz chcieć uruchamiać to co miesiąc, a nawet co tydzień.
źródło