Dlaczego warto korzystać z innodb_file_per_table?

27

Istnieje wiele artykułów przesadzających (oczywiście IMHO) innodb_file_per_table. Rozumiem, że dzięki innodb_file_per_tablelepszej kontroli nad poszczególnymi tabelami; jak tworzenie kopii zapasowych każdej tabeli osobno. Jednak żądanie lepszej wydajności jest wątpliwe.

W moim teście nie ma różnicy w wydajności innodb_file_per_tablei ibdata1dla bazy danych o pojemności 60 GB. Oczywiście był to prosty test z normalnymi zapytaniami, a sytuacja może być inna w przypadku skomplikowanych zapytań w prawdziwym życiu (to jest powód, dla którego zadałem to pytanie). 64-bitowy system Linux ext4może skutecznie obsługiwać duże pliki.

Dzięki innodb_file_per_tablewięcej operacji dyskowych we / wy jest potrzebnych; i jest to znaczące w skomplikowanych JOINsi FOREIGN KEYograniczeniach.

Obszar tabel jest współdzielony na singlu ibdata; w jaki sposób dedykowane obszary tabel dla oddzielnych tabel mogą zaoszczędzić miejsce na dysku? Oczywiście łatwiej jest zwolnić miejsce na stole dla każdego stołu ALTER, ale nadal jest to kosztowny proces (z blokadą stołu).

PYTANIE: Czy innodb_file_per_tablema wpływ na lepszą wydajność mysql? Jeśli tak, dlaczego?

Googlebot
źródło
Pomocna może być także odpowiedź na moje pytanie: dba.stackexchange.com/questions/7924/… .
KM.

Odpowiedzi:

19

Nie sądzę, że jest to kwestia wydajności, ale zarządzania.

Dzięki osobnemu plikowi na tabelę możesz na przykład przechowywać różne bazy danych w różnych urządzeniach pamięci masowej.

Możesz poradzić sobie z przypadkiem bardzo dużych baz danych w systemach plików, które nie obsługują dużych plików (przynajmniej odłóż problem, dopóki jedna tabela nie osiągnie limitu rozmiaru pliku).

Nie masz niekontrolowanego wzrostu przestrzeni tabel. Jeśli upuszczasz duże tabele, ibdataplik pozostaje mały.

Jednym aspektem, który może mieć pewien wpływ na wydajność, jest fragmentacja danych tabeli i indeksów, które będą ograniczone na tabelę. Ale to wymaga przetestowania.

ypercubeᵀᴹ
źródło
Wzrost obszaru tabel jest dokładnie tym, czego chcesz innodb_file_per_table.
sjas
13

Dlaczego warto korzystać z innodb_file_per_table?

Ponieważ łatwiej jest zarządzać pojedynczymi osobami, ponieważ można to zrobić na poziomie pliku. Oznacza to, że nawet jeśli serwer nie działa, nadal możesz kopiować dane, kopiując pliki tabel, natomiast użycie współużytkowanego obszaru tabel oznacza albo skopiowanie wszystkiego, co może być niepotrzebnie ogromne, albo znalezienie sposobu na uruchomienie serwera w celu wyodrębnienia danych ( naprawdę nie chcesz ręcznie wyodrębniać danych za pomocą edytora szesnastkowego).

Ktoś ostrzegł, że nie można po prostu kopiować i wklejać .ibdplików z jednego serwera na inny. Może to być prawda, ale nie powinno to mieć zastosowania do kopii zapasowych na tym samym serwerze (używam tutaj terminu „ kopia zapasowa” w tradycyjnym sensie robienia kopii, tj. Bez radykalnej zmiany całości). Co więcej, ibdata1jest automatycznie odtwarzany przy uruchamianiu (jak widać w kroku usuwaniaibdata1 większości przewodników „konwersja do pliku na tabelę”). W związku z tym nie musisz kopiować ibdata1oprócz .ibdplików (i odpowiadających im .frmplików itp.).

Jeśli próbujesz odzyskać utraconą tabelę, powinno wystarczyć skopiowanie jej .ibdi .frmpliku, a także information_schema(który jest znacznie mniejszy niż ibdata1). W ten sposób możesz umieścić je na fałszywym serwerze i wyodrębnić swój stół bez konieczności kopiowania całej, ogromnej rzeczy.

Jednak żądanie lepszej wydajności jest wątpliwe. … Z innodb_file_per_table potrzeba więcej operacji dyskowych we / wy; jest to znaczące w przypadku skomplikowanych JOIN i ograniczeń FOREIGN KEY.

Nic dziwnego, że wydajność zależeć będzie całkowicie od konkretnej używanej bazy danych. Jedna osoba będzie miała (nawet bardzo) różne wyniki od drugiej.

Prawdą jest, że będzie więcej operacji dyskowych we / wy z plikami na tabelę, ale tylko nieznacznie więcej. Pomyśl o tym, jak działa system.

  • W przypadku monolitycznej bazy danych:

    1. Serwer jest uruchomiony
    2. ibdata1 jest otwarty
    3. Nagłówek i metadane są odczytywane
    4. Struktury i metadane są buforowane w pamięci
    5. Występują zapytania
      1. Serwer uzyskuje dostęp do dysku i odczytuje dane z już otwartego ibdata1
      2. Serwer może buforować dane w pamięci
  • W przypadku bazy danych dla tabeli:

    1. Serwer jest uruchomiony
    2. ibdata1 jest otwarty
    3. Nagłówek i metadane są odczytywane
    4. Każdy pojedynczy .ibdplik jest otwierany
    5. Nagłówek i metadane są odczytywane z każdego .ibdpliku
    6. Struktury i metadane są buforowane w pamięci
    7. Występują zapytania
      1. Serwer uzyskuje dostęp do dysku i odczytuje dane z już otwartego .ibdpliku
      2. Serwer może buforować dane w pamięci

Zauważysz, że gdy serwer działa, nie możesz przenieść plików danych, ponieważ serwer ma do nich otwarte uchwyty. Wynika to z tego, że kiedy się uruchamia, otwiera je i pozostawia otwarte. Nie otwiera i nie zamyka ich dla każdego zapytania.

W związku z tym na początku, gdy serwer uruchamia się, jest tylko kilka operacji We / Wy; nie podczas działania. Ponadto, chociaż każdy pojedynczy .ibdplik ma swój własny narzut (podpisy plików, struktury itp.), Są one buforowane w pamięci i nie są ponownie odczytywane dla każdego zapytania. Co więcej, te same struktury są odczytywane nawet przy współużytkowanym obszarze tabel, więc nie ma prawie żadnej (jeśli w ogóle) dodatkowej pamięci.

Czy innodb_file_per_table ma wpływ na lepszą wydajność mysql?

W rzeczywistości wydajność może być gorsza .

Podczas korzystania ze wspólnego obszaru tabel operacje odczytu i zapisu mogą czasami / często być łączone, dzięki czemu serwer odczytuje próbkę danych z wielu tabel za jednym razem ibdata.

Jeśli jednak dane są rozłożone na wiele plików, musi wykonać osobną operację we / wy dla każdego z nich osobno.

Oczywiście jest to znów całkowicie zależne od danej bazy danych; rzeczywisty wpływ na wydajność zależeć będzie od wielkości, częstotliwości zapytań i wewnętrznej fragmentacji udostępnionego obszaru tabel. Niektóre osoby mogą zauważyć dużą różnicę, podczas gdy inne mogą nie odczuwać żadnego wpływu.

Obszar tabel jest współdzielony na pojedynczym ibdata; w jaki sposób dedykowane obszary tabel dla oddzielnych tabel mogą zaoszczędzić miejsce na dysku?

To nie. Jeśli już, to trochę zwiększa wykorzystanie dysku.

Nie mam bazy danych o pojemności 60 GB do przetestowania, ale moja „marna” osobista baza danych, która zawiera moją instalację WordPress i kilka małych tabel do użytku osobistego i testowania rozwoju, ważyła około 30 MB podczas korzystania ze wspólnego obszaru tabel. Po przekonwertowaniu go na plik na tabelę nadęty do ~ 85 MB. Nawet po usunięciu wszystkiego i ponownym zaimportowaniu wciąż miał> 60 MB.

Wzrost ten wynika z dwóch czynników:

  • Absolutne minimum rozmiar ibdata1jest-z jakiegoś powodu-10MB, nawet jeśli nie masz nic, ale information_schemaprzechowywane w nim.

  • W przypadku wspólnego obszaru tabel ibdata1ma tylko narzuty, takie jak podpisy plików, metadane itp., Ale w przypadku tabeli każdy .ibdplik ma to wszystko. Oznacza to, że suma (nawet przy hipotetycznym <10 MB ibdata1) byłaby nieco większa o co najmniej:

    GetTotalSizeofOverhead() * GetNumTables()

Oczywiście nie będą to olbrzymie wzrosty (chyba że używasz hosta, który ogranicza rozmiar bazy danych lub przechowuje je na dysku flash itp.), Ale mimo to zwiększają się i podczas przełączania ( każdej ) tabeli na plik - przy stole można zmniejszyć ibdata1do 10 MB, całkowita suma będzie niezmiennie większa niż była.

Synetech
źródło
11

To jest mój powód, dla którego ZAWSZE korzystaj z tabeli_pliku_wnodb:

Bez pliku na tabelę plik ibdata nigdy się nie kompresuje, nie kurczy ani nie zmniejsza w przestrzeni. Nie kiedy usuwasz wiersz, upuszczasz tabelę lub bazę danych. 2 GB danych może w krótkim czasie stać się plikiem 20 GB, jeśli masz aktywny system kolejkowania.

Załóżmy, że chcesz wykonać kopię zapasową bieżącej tabeli 1 GB przed zmianą, a następnie upuść ją później. Utknąłeś z GB nieużywanego miejsca w ibdata. Bummer.

Prawdopodobnie istnieją nieskończone przykłady przypadków, w których środki tymczasowe nadmuchują pojedynczy plik danych, ale wystarczy powiedzieć, że moim zdaniem nigdy nie ma powodu, aby NIE używać innodb_file_per_table

Oto dobry post do przeczytania: http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table

randomx
źródło
1
Uświadomiłem sobie, że dobrze jest ZAWSZE to robić. Magnetyczne macierze pamięci masowej wspierane przez dyski SSD mogą skuteczniej obsługiwać pamięć podręczną odczytu / zapisu względem mniejszych plików tabel. W przypadku wielu tabel, które w 99,99% przypadków są po prostu „czytane”, ale nie zapisywane, zawsze znajdują się w pamięci podręcznej kontrolera pamięci, co znacznie skraca czas odpowiedzi.
sdkks,
5

Moim powodem, dla którego nie należy używać innodb_file_per_table, jest wydajność.

Zrobiłem kilka testów dla naszej bazy danych z 450 tabelami na mysql 5.5.45 Linux CentOS wydanie 6.7

W przypadku testów jednostkowych, które wstawiają urządzenia do bazy danych przed każdym testem (nieużywanie wszystkich tabel za każdym razem), a także same testy często działają z bazą danych (wstawia, aktualizuje, usuwa, wybiera) wydajność była 3-5 razy lepsza, gdy tabele bazy danych nie były podzielone na więcej plików.

Zalecam przetestowanie bazy danych za pomocą zapytań, których chcesz użyć, i porównanie jej przed podjęciem decyzji o użyciu pliku innodb_file_per_table

Być może dowiesz się, że w przypadku serwera produkcyjnego możesz użyć innodb_file_per_table, ale w środowisku CI (kontynuacja integracji), który rozpoczyna testy jednostkowe (często korzysta z DB), a także programistom, którzy dużo rozpoczynają testy jednostkowe, lepiej nie używać go ze względu na wydajność.

Tomor
źródło
2
Zgaduję, że wynika to z czasu potrzebnego do przydzielenia plików początkowych dla wszystkich 450 tabel w porównaniu do przydzielenia jednego pliku. W produkcji stanie się to tylko raz, więc nie powinno to stanowić problemu, ale dobrze jest, że dla szybkiego utworzenia bazy danych, a następnie całkowitego jej rozebrania i powtarzania w kółko jednego pliku ibdata jest lepsze.
ColinM
2

Ułatwia to zarządzanie danymi, ponieważ można odzyskać nieużywane miejsce, co jest miłe.

Myślę, że jeśli twoja baza danych jest używana głównie do wybranych zapytań, nie wpłynie to znacząco na wydajność. Nadal musi czytać o tej samej ilości danych. Nie sądzę, żeby miało to znaczenie, z jakich plików odczytuje dane.

Może to jednak pogorszyć wydajność bazy danych, która wykonuje wiele wstawek i aktualizacji. Wynika to z faktu, że mysql wywołuje fsync () w pliku pamięci po zatwierdzeniu transakcji. Jeśli istnieje jeden plik, wykonuje on jedno połączenie i czeka na zakończenie połączenia. Jeśli jest wiele plików, musi wykonać połączenie wiele razy i poczekać, aż wszystkie te wywołania zostaną zwrócone, zanim polecenie commit może wrócić.

Oto post od osoby, która doświadczyła tego problemu: http://umangg.blogspot.com/2010/02/innodbfilepertable.html

Sarel Botha
źródło
2

Jak wynika z poniższego artykułu, wydajność nie polega na zarządzaniu danymi (same operacje crud), ale raczej na tworzeniu i upuszczaniu obiektów.

innodb_file_per_table sprawia, że ​​masowe tworzenie i upuszczanie obiektów jest wolniejsze niż przechowywanie ibdata, a do produkcji nie ma zastosowania, ale powinien być odpowiedni do ciągłego testowania.

https://www.percona.com/blog/2015/02/24/mysqls-innodb_file_per_table-slowing/

Flavio Peinado
źródło