Pewnym sposobem na przyspieszenie ALTER TABLE jest usunięcie niepotrzebnych indeksów
Oto pierwsze kroki, aby załadować nową wersję tabeli
CREATE TABLE s_relations_new LIKE s_relations;
#
# Drop Duplicate Indexes
#
ALTER TABLE s_relations_new
DROP INDEX source_persona_index,
DROP INDEX target_persona_index,
DROP INDEX target_persona_relation_type_index
;
Uwaga:
Upuściłem source_persona_index, ponieważ jest to pierwsza kolumna w 4 innych indeksach
- Unique_target_persona
- unikatowy cel
- source_and_target_object_index
- source_target_persona_index
Upuściłem cel_persona_index, ponieważ jest to pierwsza kolumna w 2 innych indeksach
- target_persona_relation_type_index
- target_persona_relation_type_message_id_ind_index
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:
SELECT COUNT(DISTINCT sent_at) FROM s_relations;
SELECT COUNT(DISTINCT message_id) FROM s_relations;
SELECT COUNT(DISTINCT target_object_id) FROM s_relations;
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.
- Jeśli
COUNT(DISTINCT sent_at)
> 4 000 000
- następnie
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Jeśli
COUNT(DISTINCT message_id)
> 4 000 000
- następnie
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Jeśli
COUNT(DISTINCT target_object_id)
> 4 000 000
- następnie
ALTER 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
#
# Change the Column Name
# Load the Table
#
ALTER TABLE s_relations_new CHANGE sent_at sent_at_new int(11) DEFAULT NULL;
INSERT INTO s_relations_new SELECT * FROM s_relations;
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):
$ service mysql restart --skip-networking
Następnie zaloguj się do mysql i załaduj te ostatnie wiersze:
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Następnie uruchom ponownie mysql normalnie
$ service mysql restart
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:
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations_old WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Spróbuj !!!
CAVEAT: Gdy będziesz zadowolony z tej operacji, możesz upuścić stary stół w najbliższym dogodnym momencie:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
, pokaż, że kolumna musi zmienić, typ danych kolumny, a nowa nazwa kolumny.