2012-10-08 12 views
34

Dlaczego aktualizacja tabeli po prostu zajmuje więcej niż godzinę, aby dodać kolumnę? Ta tabela ma 15 milionów wierszy. Ma 2 indeksy i pojedynczy klucz podstawowy. Zapytanie ALTER TABLE znajdowało się w stanie "Kopiuj do tabeli tmp" przez 1 godzinę i 15 minut.MySQL bardzo wolno dla zapytania tabeli zmian

ALTER TABLE `frugg`.`item_catalog_map` 
ADD COLUMN `conversion_url` TEXT NULL DEFAULT NULL 

Tabela:

mysql> describe item_catalog_map; 
+------------------------+---------------+------+-----+---------+-------+ 
| Field     | Type   | Null | Key | Default | Extra | 
+------------------------+---------------+------+-----+---------+-------+ 
| catalog_unique_item_id | varchar(255) | NO | PRI | NULL |  | 
| catalog_id    | int(11)  | YES | MUL | NULL |  | 
| item_id    | int(11)  | YES | MUL | NULL |  | 
| price     | decimal(10,2) | YES |  | 0.00 |  | 
+------------------------+---------------+------+-----+---------+-------+ 

mysql> show index from item_catalog_map; 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table   | Non_unique | Key_name    | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| item_catalog_map |   0 | PRIMARY    |   1 | catalog_unique_item_id | A   | 15485115 |  NULL | NULL |  | BTREE  |   | 
| item_catalog_map |   1 | IDX_ACD6184FCC3C66FC |   1 | catalog_id    | A   |   18 |  NULL | NULL | YES | BTREE  |   | 
| item_catalog_map |   1 | IDX_ACD6184F126F525E |   1 | item_id    | A   | 15485115 |  NULL | NULL | YES | BTREE  |   | 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
+1

Może ten wątek z podobnym pytaniem będzie ci pomóc ... http: //stackoverflow.com/questions/1359097/mysql-alter-table-on-very-large-table-is-it-safe-to -run-it –

+1

Przejście tego wątku również ... http: //stackoverflow.com/questions/5677932/optimize-mysql-for-faster-alter-table-add-column –

+0

byłoby super, gdyby to był jakiś rodzaj paska postępu, komunikatu statusu lub przynajmniej kursora, LOL. Zwłaszcza, że ​​"Modyfikuj kolumnę" zabrało moją stronę w trybie offline. –

Odpowiedz

45

Wydajność ALTER TABLE MySQL może stać się problemem przy bardzo dużych tabelach. MySQL wykonuje większość zmian, tworząc pustą tabelę z żądaną nową strukturą, wstawiając wszystkie dane ze starej tabeli do nowej i usuwając starą tabelę. Może to zająć dużo czasu, zwłaszcza jeśli brakuje ci pamięci, a stół jest duży i ma wiele indeksów. Wiele osób ma doświadczenie w operacjach ALTER TABLE, które trwały wiele godzin lub dni.

W każdym razie, jeśli chcesz kontynuować alter tabeli, może następujące zasoby mogą pomóc:

+3

Jeśli zajmie to dużo czasu, coś jest nie tak z twoim systemem pamięci masowej, to nie jest sprawa MySQL. – AndreKR

+0

im zmiany z varchar do tekstu w tabeli 30 wierszy, czekałem przez 20 minut i nadal trwa. Co to może być ? – kommradHomer

+0

VARCHAR jest przechowywany w tabeli, podczas gdy tekst jest przechowywany oddzielnie i odniesienia są przechowywane w tabeli. Są więc bardzo różne. Zakładam, że zmiana została wywołana, ponieważ masz bardzo duży varchar i chcesz pozwolić na znacznie większe wartości. W takim przypadku musi przenieść wszystkie wartości. – techdude

7

Twój stół ma 15 milionów wierszy, które jest czymś. Tabela ALTER łączy się z kopiowaniem wszystkich danych z tabeli i odtwarzaniem indeksów. Jako pierwszy pomiar spróbuj skopiować plik danych (item_catalog_map.MYD, jeśli to MyISAM) w swoim systemie plików i zobacz, ile czasu to zajmie. Jest to czas, w którym ALTER TABLE wykona co najmniej.

5

Dla zminimalizowania blokowania się z dużą tabela, którą chcę zmienić, wykonaj następujące czynności:

  • Utwórz nową pustą tabelę na podstawie istniejącej tabeli i zmień tę nową pustą tabelę.
  • Wykonaj mysqldump z dużym stołem tak, że ma jeden kompletny instrukcji insert dla każdego rekordu w dużym stole (przełączniki -ci --skip-rozszerzony-insert)
  • zaimportować mysqldump do innej bazy danych (pusty) z pustą zmienioną nazwą duża_tabela.
  • Weź mysqldump tej nowej tabeli przemianowania z innej bazy danych, a następnie zaimportować je do oryginalnej bazy danych
  • Zmień nazwę large_table i large_table_new w oryginalnej bazie danych.

    mysql> create table DATABASE_NAME.LARGE_TABLE_NEW like DATABASE_NAME.LARGE_TABLE; 
    mysql> alter table DATABASE_NAME.LARGE_TABLE_NEW add column NEW_COLUMN_NAME COL_DATA_TYPE(SIZE) default null; 
    
    $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p DATABASE_NAME LARGE_TABLE > LARGE_TABLE.sql 
    
    mysql> create table test.LARGE_TABLE like DATABASE_NAME.LARGE_TABLE; 
    
    $ mysql -u root -p -D test < LARGE_TABLE.sql 
    
    mysql> rename table test.LARGE_TABLE to test.LARGE_TABLE_NEW; 
    
    $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p test LARGE_TABLE_NEW > LARGE_TABLE_NEW.sql 
    
    $ mysql -u root -p -D DATABASE_NAME < LARGE_TABLE_NEW.sql 
    
    mysql> rename table DATABASE_NAME.LARGE_TABLE to DATABASE_NAME.LARGE_TABLE_OLD, DATABASE_NAME.LARGE_TABLE_NEW to DATABASE_NAME.LARGE_TABLE; 
    
7

Narzędzia Percona są ratownik dla tego materiału w/dużych tabelach.

http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html

one zasadniczo:

  1. utworzyć duplikat tabeli
  2. utworzyć wyzwalacz do synchronizacji tabel
  3. zbiorcze dane kopiowania
  4. zweryfikować
  5. swapowych tabele

Trwa wiecznie, ale kogo to obchodzi, ponieważ oznacza to, że możesz zmieniać kolumny bez przestojów.

+1

nic nie pomoże, jeśli masz zagraniczne klucze na swoich stołach, ponieważ nie możesz atomicznie zmienić nazwy dwóch stołów – kommradHomer

14

Jeśli nie masz nic przeciwko przestojom, moja sugestia polega na użyciu trzech oddzielnych instrukcji: ALTER TABLE. Pierwsza instrukcja usuwa wszystkie istniejące indeksy dodatkowe. Druga instrukcja dotyczy wszystkich zmian związanych z kolumną. Ostatnia instrukcja dodaje pomniejsze indeksy wtórne i stosuje inne zmiany indeksów.

Kolejne dwie wskazówki:

  1. przed zastosowaniem zmian indeksu, należy wykonać dwa następujące oświadczenia i zmienić wartości z powrotem do 1 po zakończeniu zmiany indeksu.

    SET unique_checks=0; 
    SET foreign_key_checks=0; 
    
  2. Kiedy utworzyć wiele indeksów wtórnych, umieścić je w jednym ALTER TABLE oświadczenia zamiast wielu oddzielone ALTER TABLE oświadczenia.

Poniższy rysunek pokazuje różnicę wydajności. Podejście 1 to twoje podejście, a podejście 2 to moja droga. Podejście 2 zajmuje około 3,47% czasu w porównaniu z podejściem 1 dla stołu 50m. Rozwiązanie działa tylko w przypadku silnika MySQL (> = 5.5) InnoDB.

enter image description here

0

Jeśli zmienia się kilka kolumn na raz może zająć więcej czasu niż można się spodziewać. Zamiast tego spróbuj zmienić jedną kolumnę na raz. Nie znajduję strony technicznej tego problemu, ale doświadczyłem problemu i doszedłem do tego.

Powiązane problemy