Mam tabelę InnoDB, którą chcę zmienić. Tabela ma ~ 80 milionów wierszy i zamknęła kilka indeksów.
Chcę zmienić nazwę jednej z kolumn i dodać jeszcze kilka indeksów.
- Jaki jest najszybszy sposób na zrobienie tego (zakładając, że mogę cierpieć nawet z powodu przestojów - serwer jest nieużywanym urządzeniem podrzędnym)?
- Czy „proste”
alter table
, najszybsze rozwiązanie?
W tej chwili liczy się tylko szybkość :)
mysql
innodb
alter-table
ddl
Biegł
źródło
źródło
SHOW CREATE TABLE tblname\G
, pokaż, że kolumna musi zmienić, typ danych kolumny, a nowa nazwa kolumny.sent_at
i dodać kilka innych wskaźnikówOdpowiedzi:
Pewnym sposobem na przyspieszenie ALTER TABLE jest usunięcie niepotrzebnych indeksów
Oto pierwsze kroki, aby załadować nową wersję tabeli
Uwaga:
Upuściłem source_persona_index, ponieważ jest to pierwsza kolumna w 4 innych indeksach
Upuściłem cel_persona_index, ponieważ jest to pierwsza kolumna w 2 innych indeksach
Upuściłem cel_persona_relation_type_index, ponieważ pierwsze 2 kolumny są również w target_persona_relation_type_message_id_index
OK To zajmuje się niepotrzebnymi indeksami. Czy są jakieś indeksy o niskiej liczności? Oto sposób, aby ustalić, że:
Uruchom następujące zapytania:
Zgodnie z Twoim pytaniem istnieje około 80 000 000 wierszy. Zasadniczo optymalizator zapytań MySQL nie będzie korzystał z indeksu, jeśli liczność wybranych kolumn jest większa niż 5% liczby wierszy tabeli. W tym przypadku byłoby to 4 000 000.
COUNT(DISTINCT sent_at)
> 4 000 000ALTER TABLE s_relations_new DROP INDEX sent_at_index;
COUNT(DISTINCT message_id)
> 4 000 000ALTER TABLE s_relations_new DROP INDEX message_id_index;
COUNT(DISTINCT target_object_id)
> 4 000 000ALTER TABLE s_relations_new DROP INDEX target_object_index;
Po określeniu przydatności lub bezużyteczności tych indeksów można ponownie załadować dane
To jest to, prawda? NIE !!!
Jeśli twoja strona działała cały czas, być może INSERT działa przeciwko s_relations podczas ładowania s_relations_new. Jak odzyskać brakujące wiersze?
Znajdź maksymalny identyfikator w s_relations_new i dołącz wszystko po tym identyfikatorze z s_relations. Aby upewnić się, że tabela jest zamrożona i używana tylko do tej aktualizacji, musisz mieć trochę przestoju w celu uzyskania tych ostatnich wierszy, które zostały wstawione do s_relation_new. Oto co robisz:
W systemie operacyjnym uruchom ponownie mysql, aby nikt inny nie mógł się zalogować, ale root @ localhost (wyłącza TCP / IP):
Następnie zaloguj się do mysql i załaduj te ostatnie wiersze:
Następnie uruchom ponownie mysql normalnie
Teraz, jeśli nie możesz zdjąć mysql, będziesz musiał zrobić przynętę i przełączyć na s_relations. Zaloguj się do mysql i wykonaj następujące czynności:
Spróbuj !!!
CAVEAT: Gdy będziesz zadowolony z tej operacji, możesz upuścić stary stół w najbliższym dogodnym momencie:
źródło
Prawidłowa odpowiedź zależy od używanej wersji silnika MySQL.
W przypadku korzystania z wersji 5.6+ zmiana nazw oraz dodawanie / usuwanie indeksów odbywa się online , tzn. Bez kopiowania wszystkich danych tabeli.
Po prostu użyj,
ALTER TABLE
jak zwykle, będzie to w większości przypadków zmiana nazw i spadków indeksów oraz dość szybkie dodawanie indeksów (tak szybko, jak jednorazowe odczytanie całej tabeli).Jeśli używasz 5.1+, a wtyczka InnoDB jest włączona, dodawanie / usuwanie indeksów będzie również dostępne online. Nie jestem pewien co do zmian nazw.
Jeśli używasz starszej wersji,
ALTER TABLE
nadal jest najszybsza - ale prawdopodobnie będzie strasznie powolna, ponieważ wszystkie twoje dane zostaną ponownie wstawione do tymczasowej tabeli pod maską.Wreszcie czas na obalenie mitu. Niestety nie mam tutaj dość karmy, aby komentować odpowiedzi, ale uważam, że ważne jest, aby poprawić najczęściej głosowaną odpowiedź. To jest złe :
W rzeczywistości jest na odwrót .
Wskaźniki są przydatne do wyboru kilku wierszy, dlatego ważne jest, aby miały wysoką liczność, co oznacza wiele odrębnych wartości i statystycznie kilka wierszy o tej samej wartości.
źródło
RENAME TABLE
natychmiast (zgodnie z oczekiwaniami), aleCHANGE COLUMN
aby zmienić nazwę klucza podstawowego zrobiłem pełną kopię ... 7 godzin! Być może tylko dlatego, że był to klucz podstawowy? Niedobrze.Miałem ten sam problem z Maria DB 10.1.12, a następnie po przeczytaniu dokumentacji stwierdziłem, że istnieje opcja wykonania operacji „w miejscu”, która eliminuje kopię tabeli. Dzięki tej opcji tabela zmian jest bardzo szybka. W moim przypadku było to:
to jest bardzo szybkie. Bez opcji algorytmu nigdy by się nie skończyło.
https://mariadb.com/kb/en/mariadb/alter-table/
źródło
W przypadku zmiany nazwy kolumny
powinno być w porządku i nie powodować przestojów.
W przypadku indeksów instrukcja CREATE INDEX zablokuje tabelę. Jeśli jest to nieużywany niewolnik, jak wspomniałeś, to nie jest problem.
Inną opcją byłoby utworzenie zupełnie nowej tabeli, która ma odpowiednie nazwy kolumn i indeksy. Następnie możesz skopiować do niego wszystkie dane, a następnie wykonać serię
Pozwoliłoby to zminimalizować czas przestoju kosztem tymczasowego zużycia dwukrotnie większej przestrzeni.
źródło
Mam również ten problem i użyłem tego SQL:
Mam nadzieję, że to może komuś pomóc
Pozdrowienia,
Wola
źródło