2011-08-27 14 views
9

Mam dużą tabelę MySQL (~ 10 milionów wierszy, 6.5G), które używam do odczytu & write. To MyISAM, i otrzymuję wiele blokad ze względu na blokadę stołu MyISAM podczas pisania.InnoDB vs. czas wprowadzania zapytania MyISAM

Postanowiłem spróbować przejść do InnoDB, który jest zalecany dla tabel do odczytu/zapisu, i blokuje tylko określone wiersze podczas zapisywania.

Po konwersji przetestowałem instrukcje wstawiania i okazuje się, że zajmuje to około 15 razy więcej (od 0,1 sekundy do 1,5 sekundy) w tabeli InnoDB niż w tabeli MyISAM. Dlaczego?

Nie skonfigurowałem jeszcze niczego dla InnoDB i planuję dodać również partycje, ale ta liczba jest dla mnie wciąż nieoczekiwana. Oczywiście tabele są takie same, te same indeksy itp

Dodatkowe informacje zgodnie z życzeniem:

2 indeksy. primary to data_id typu Big INT, a nie unikatowy id_użytkownika typu varchar (255).

Wkładki mają ~ 150 wierszy, które mają ten sam identyfikator użytkownika.

Rozmiar indeksów: 200 MB w MyISAM, InnoDB w 400MB

+3

Czy możesz pokazać nam indeksy? Jest to najbardziej prawdopodobna przyczyna długich czasów wstawiania. – wallyk

+0

Mam 2 indeksy, id_danych, który jest kluczem podstawowym, i identyfikator użytkownika, który nie jest unikalny. Moje wstawki mają ~ 150 wierszy, które mają ten sam identyfikator użytkownika (który ma indeks). – normalppl

+0

, ale jaka jest zawartość każdego indeksu? Jeśli jest kilka pęknięć, to na pewno trudno będzie indeksować. Ale jeśli są to liczby całkowite lub inne trywialne, to trudniej jest zrozumieć, dlaczego wydajność byłaby zła. – wallyk

Odpowiedz

5

related answer sugeruje, że ustawienie zmiennej innodb_flush_log_at_trx_commit do 2 jest prawdopodobne, aby zwiększyć wydajność, gdy stosunek do zapisu odczytuje jest stosunkowo wysoki. Aby uzyskać więcej informacji, patrz the documentation.

+0

Teraz testuję tylko teraz. więc żadne odczyty, tylko jedna wkładka z 150 rzędów, nie chcą tego najpierw wymyślić. – normalppl

+1

To zrobiło dla mnie ogromną różnicę. Wstawienie 7500 wierszy bez zmiany 'innodb_flush_log_at_trx_commit' zajęło 5 minut. Zmiana na 0 lub 2 zmniejszyła to samo INSERT do 3 sekund. – qris

3

Należy pamiętać, że sposób obsługi klawiszy InnoDB może powodować problemy. Ponieważ wszystko jest przechowywane na dysku w kolejności, w której klucz podstawowy ma nieautomatyczny przyrost klucz podstawowy może spowodować przeniesienie dużej części tabeli na dysk z dowolną wstawką (napotkałem ten problem, gdy miałem tabelę przestawną i użyłem połączone identyfikatory jako klucz podstawowy). Przenoszenie danych na dysku jest wolne.

Również rozmiary indeksu mogą być znacznie większe w InnoDB, ponieważ każdy indeks zawiera również klucz podstawowy. Sprawdź, czy nie masz żadnych limitów pamięci.

+0

Nie spodziewałem się, że będzie szybciej, zdaję sobie sprawę, że ma pomóc w wielu odczytach. Ale jeśli podstawowa wkładka, którą zwykle wykonuję, zajmuje 15 razy więcej (od 0,1 sekundy do 1,5 sekundy), to brzmi jak coś jest nie w porządku, nie? – normalppl

+1

Tak, przepraszam, czytaj jako 15%, nie 15-krotnie - prawdopodobnie istnieje problem – jisaacstone

4

Wydaje mi się, że InnoDB implementuje prawdziwy ACID i robi dużo fsync() s, aby zapisać dane. I MyISAM nie jest prawdziwym ACID i robi mniej fsync().

There are recomendations to kill fsync gdy trzeba załadować ogromne danych w

If you want to load data into InnoDB quickly: 
* use as large an InnoDB buffer cache as possible 
* make the InnoDB log files as large as possible 
* minimize the number of unique indexes on your tables 
* disable all calls to fsync from InnoDB. You have to hack the code to 
get this, or look at the Google patch. Of course, you only want to run 
in this mode when loading the table. 

And lists says:

MyISAM zawsze biegnie w trybie 'nosync', to znaczy, że nigdy nie wywołuje fsync() w celu wypłukania pliki do dysku .

Nosync InnoDB jest przydatny w testowaniu, jeśli jakiś OS/komputer jest bardzo wolny w fsync(). Ale nie powinno być używane w systemie produkcyjnym.

Ten sam komunikat mówi, że czasami InnoDB używa innej metody synchronizacji:

Następnie InnoDB używa fsync() do spłukiwania zarówno dane i pliki dziennika.Jeśli określono O_DSYNC na , InnoDB używa O_SYNC do otwierania i opróżniania plików dziennika, ale używa fsync() w celu opróżnienia plików danych. Jeśli określono O_DIRECT (dostępny w niektórych wersjach Linux, począwszy od MySQL-4.0.14), InnoDB używa O_DIRECT do otwierania plików danych i używa fsync() do opróżniania zarówno danych, jak i plików dziennika. Zauważ, że InnoDB nie używa fdatasync() ani O_DSYNC, ponieważ były problemy z nimi związane w wielu smakach Uniksa.

2

Najpierw Twój test jest nieważny, ponieważ przyrost prędkości blokowania na poziomie wiersza przed blokowaniem poziomie tabeli jest, gdy masz współbieżność! Dzięki 1 wkładkom do gwintowania masz 1 blokadę/odblokowanie na wkładkę w obu przypadkach, a wkładki nie czekają na zwolnienie blokady stołu.

Sekund, jak stwierdził JIStone, niesekwencyjny klucz podstawowy to zabójca wydajności dla wkładek, gdy rozmiar stołu jest większy niż puli buforów.

Po trzecie, wielkość puli buforów jest jednym z najważniejszych ustawień w InnoDB. Uczyń go jak najlżejszym (zalecane ustawienie to 80% dostępnej pamięci RAM).

Następnie, jak stwierdził @wallyk, innodb_flush_log_at_trx_commit mają kluczowe znaczenie dla szybkości operacji we/wy.

Następnie ważne są wartości innodb_log_file_size i innodb_buffer_file_size.

Następnie należy pamiętać, że ponieważ masz dwa unikatowe indeksy, zanim InnoDB może wstawić wiersz, musi sprawdzić istnienie wartości w indeksach, a indeksy są duże.

Bez szczegółowych informacji na temat tabeli i indeksów, nie mogę udzielić Ci więcej porad, ale należy pamiętać, że żaden aparat pamięci masowej nie jest panaceum i chociaż często można uzyskać dużą szybkość, po prostu zmieniając silnik pamięci masowej, dodawanie indeksu lub podkręcanie jednej zmiennej, w dużych systemach, rzeczy są bardziej złożone niż to. Ale, jak już powiedziałem, nie powinieneś porównywać prędkości wstawiania surowca w izolowanym teście, musisz wykonać test tak blisko rzeczywistej aplikacji, jak to tylko możliwe.

aktualizacja: jedna wskazówka Zarówno MyISAM i InnoDB, multi-insert (insert into .... wartości (...), (...), (...)) jest szybsza. Ponadto w InnoDB możesz tworzyć inserty w transakcjach, które wyłączają aktualizowanie nieunikalnych indeksów przed zakończeniem transakcji, a także są szybsze (ale nie wykonuj dużych transakcji, ponieważ spowalnia to działanie z powodu zastosowanego poziomu izolacji i sposób działania wersji wiersza).