MySQL OPTYMALIZOWAĆ wszystkie tabele?


245

MySQL ma polecenie OPTIMIZE TABLE, którego można użyć do odzyskania nieużywanego miejsca w instalacji MySQL. Czy istnieje sposób (wbudowana komenda lub wspólna procedura przechowywana), aby uruchomić tę optymalizację dla każdej tabeli w bazie danych i / lub instalacji serwera, czy jest to coś, co musiałbyś sam napisać?


11
Bądź ostrożny, ponieważ niekoniecznie zwróci przestrzeń. Jeśli używasz InnoDB z pojedynczym plikiem (prawdopodobnie najbardziej powszechnym w dzisiejszych czasach), a nie z oddzielnymi plikami na tabelę, na końcu będziesz nadal używać tej samej ilości miejsca na dysku. W rzeczywistości widziałem, że faktycznie zajmuje znacznie więcej miejsca na dysku, kiedy wszystko zostało powiedziane i zrobione. Przy dużych stołach stół może być również zablokowany na bardzo długi czas.
— jmichalicek

1
OPTIMIZE TABLEbył użyteczny dla MyISAM. Teraz, gdy silnik odchodzi, potrzeba OPTIMIZE TABLEodchodzi, szczególnie potrzeba okresowej optymalizacji wszystkich tabel.
— Rick James

+1 za dobre informacje rick - ale biorąc pod uwagę standardowe praktyki w bazach danych w świecie rzeczywistym, nie zdziwiłbym się, gdyby stare tabele MyISAM pozostały przez kolejną dekadę
— Alan Storm

Odpowiedzi:


410

Możesz mysqlcheckto zrobić w wierszu polecenia.

Jedna baza danych:

mysqlcheck -o <db_schema_name>

Wszystkie bazy danych:

mysqlcheck -o --all-databases

czy poleciłbyś zaplanować uruchamianie tego polecenia co najmniej raz w miesiącu?
— Gaia,

11
Cześć @ Gaia. Niekoniecznie. Optymalizacja wszystkich tabel w danym harmonogramie nie jest korzystna dla wszystkich. Spójrz na ten post i przeczytaj komentarze, aby uzyskać więcej dogłębnych przemyśleń na ten temat, niż mogę zapewnić w ograniczonej przestrzeni tutaj: xaprb.com/blog/2010/02/07/…
— Ike Walker

18
proste użycie:mysqlcheck -u [username] -p[password] -o [database name]
— M Rostami,

38
Należy pamiętać, że tabele są zablokowane podczas wykonywania OPTYMALIZACJI, co może zająć dużo czasu, jeśli tabele zawierają dużo danych. Tak więc w czasie, gdy tabela jest OPTYMALIZOWANA, nie można wstawiać ani usuwać nowych rekordów. Zasadniczo OPTYMALIZACJA wszystkich tabel systemu produkcyjnego nie może być uważana za trywialną operację.
— Werner

2
@ No-Chip możesz zoptymalizować tabele w kliencie MySQL za pomocą OPTIMIZE TABLEpolecenia: dev.mysql.com/doc/refman/5.5/en/optimize-table.html . Na przykład zoptymalizuj jedną tabelę w ten sposób: OPTIMIZE TABLE <your_schema>.<your_table>;zoptymalizuj wszystkie tabele w danym schemacie w ten sposób:select concat('OPTIMIZE NO_WRITE_TO_BINLOG TABLE ',table_schema,'.',table_name,';') into outfile '/tmp/optimize_all_tables.sql' from information_schema.tables where table_schema = 'pabeta' and table_type = 'base table'; source /tmp/optimize_all_tables.sql;
— Ike Walker

28

Stworzyłem ten „prosty” skrypt:

set @tables_like = null;
set @optimize = null;
set @show_tables = concat("show tables where", ifnull(concat(" `Tables_in_", database(), "` like '", @tables_like, "' and"), ''), " (@optimize:=concat_ws(',',@optimize,`Tables_in_", database() ,"`))");

Prepare `bd` from @show_tables;
EXECUTE `bd`;
DEALLOCATE PREPARE `bd`;

set @optimize := concat('optimize table ', @optimize);
PREPARE `sql` FROM @optimize;
EXECUTE `sql`;
DEALLOCATE PREPARE `sql`;

set @show_tables = null, @optimize = null, @tables_like = null;

Aby go uruchomić, po prostu wklej go w dowolnym SQL IDE podłączonym do bazy danych.

Uwaga: ten kod NIE działa na phpmyadmin.

Jak to działa

Uruchamia show tablesinstrukcję i przechowuje ją w przygotowanej instrukcji. Następnie uruchamia a optimize tablew wybranym zestawie.

Możesz kontrolować, które tabele zoptymalizować, ustawiając inną wartość w var @tables_like(np set @tables_like = '%test%';. :) .


4
Moje współdzielone środowisko hostingowe nie ma dostępnego „mysqlchk”, więc mógłbym to uruchomić bezpośrednio z sesji terminala „mysql”. Dziękuję Ci!
— funwhilelost

Zapraszamy. Używam tego kodu do optymalizacji 50 baz danych i spędzam jak najmniej czasu. Jeśli uważasz, że mogę poprawić kod w jakikolwiek sposób, śmiało daj mi swoje sugestie. Z przyjemnością poprawię ten cenny fragment kodu.
— Ismael Miguel

Przygotuj bdz @b Kod błędu: 1064. Wystąpił błąd w składni SQL; sprawdź instrukcję, która odpowiada twojej wersji serwera MySQL pod kątem właściwej składni do użycia w pobliżu „NULL” w linii 1
— Paul Gregoire,

@ IsmaelMiguel to jest MySQL, twoja odpowiedź używa składni TSQL i nie będzie działać z MySQL.
— Phrancis

2
@LorenzoBelfanti Dziękujemy za potwierdzenie. Cieszę się, że nawet po 2 latach ten kod jest użyteczny dla co najmniej 10 osób. To dla mnie ogromne zwycięstwo! Jeszcze raz Ci dziękuję!
— Ismael Miguel

20

Poniższy przykładowy skrypt php może pomóc zoptymalizować wszystkie tabele w bazie danych

<?php

dbConnect();

$alltables = mysql_query("SHOW TABLES");

while ($table = mysql_fetch_assoc($alltables))
{
   foreach ($table as $db => $tablename)
   {
       mysql_query("OPTIMIZE TABLE '".$tablename."'")
       or die(mysql_error());

   }
}

?>

7
W bazie danych z 200 tabelami uruchomisz 200 osobnych zapytań, optymalizując jednocześnie 1 tabelę. Nazwy tabel należy implodować w jeden ciąg, dlatego wymagane jest tylko jedno zapytanie dotyczące tabeli optymalizacji.
— Dean Marshall

8
Zastanawiam się, czy podejście z oddzielnym zapytaniem jest czasem lepsze. MySQL mówi, że tabele są zablokowane podczas działania OPTIMIZE TABLE. Wtedy rozsądniej byłoby zoptymalizować każdą z nich na raz, aby serwer mógł uzyskać blokady na minimalny czas. Oczywiście dotyczy to serwera, który jest stale dostępny. Jeśli nie, to myślę, że jedno zapytanie jest najlepszym rozwiązaniem.
— glarrain

Jak wyglądałby skrypt, gdybyś implodował i przekształcił się w 1 zapytanie? Dzięki.
— H. Ferrence,

8
@Dean Oddzielne podejście do zapytań jest często lepsze, aby zapewnić oddech dla aplikacji na żywo. W rzeczywistości zwykle dodam opóźnienie (około 750 ms) właśnie w tym celu.
— zanlok 10.12

15

Wykonaj wszystkie niezbędne procedury, aby naprawić wszystkie tabele we wszystkich bazach danych za pomocą prostego skryptu powłoki:

#!/bin/bash
mysqlcheck --all-databases
mysqlcheck --all-databases -o
mysqlcheck --all-databases --auto-repair
mysqlcheck --all-databases --analyze

11

dla wszystkich baz danych:

mysqlcheck -Aos -uuser -p 

Dla jednej optymalizacji bazy danych:

mysqlcheck -os -uroot -p dbtest3

Przynajmniej dla mnie pod Linuksem polecenie mysqlcheck -Aosnie wymaga użytkownika + hasła.
— Zuul,

7

Z phpMyAdmin i innych źródeł możesz użyć:

SET SESSION group_concat_max_len = 99999999;
SELECT GROUP_CONCAT(concat('OPTIMIZE TABLE `', table_name, '`;') SEPARATOR '') AS O
FROM INFORMATION_SCHEMA.TABLES WHERE 
TABLE_TYPE = 'BASE TABLE'
AND table_name!='dual'
AND TABLE_SCHEMA = '<your databasename>'

Następnie możesz skopiować i wkleić wynik do nowego zapytania lub wykonać go z własnego źródła. Jeśli nie widzisz całego oświadczenia: sposób, aby zobaczyć całą instrukcję w phpmyadmin


to była miła odpowiedź, ale mój phpmyadmin nie pokazuje całego polecenia, tylko te pierwsze wtedy ... smutne dla mnie, lol.
— MonneratRJ

6

Jeśli chcesz analizować, naprawiać i optymalizować wszystkie tabele we wszystkich bazach danych na serwerze MySQL, możesz to zrobić za jednym razem z wiersza polecenia. Musisz to zrobić root.

mysqlcheck -u root -p --auto-repair --optimize --all-databases

Po uruchomieniu zostaniesz poproszony o podanie hasła root MySQL. Następnie zacznie się, a zobaczysz wyniki, jak to się dzieje.

Przykładowe dane wyjściowe:

yourdbname1.yourdbtable1       OK
yourdbname2.yourdbtable2       Table is already up to date
yourdbname3.yourdbtable3
note     : Table does not support optimize, doing recreate + analyze instead
status   : OK

etc..
etc...

Repairing tables
yourdbname10.yourdbtable10
warning  : Number of rows changed from 121378 to 81562
status   : OK

Jeśli nie znasz hasła roota i używasz WHM, możesz je zmienić z poziomu WHM, przechodząc do: Strona główna> Usługi SQL> Hasło root MySQL


5

Z linii poleceń:

mysqlcheck -o <db_name> -u<username> -p

następnie wpisz hasło


4

Możesz zoptymalizować / sprawdzić i naprawić wszystkie tabele bazy danych, używając klienta mysql.

Po pierwsze, powinieneś uzyskać listę wszystkich tabel oddzielonych znakami „,”:

mysql -u[USERNAME] -p[PASSWORD] -Bse 'show tables' [DB_NAME]|xargs|perl -pe 's/ /,/g'

Teraz, gdy masz listę wszystkich tabel do optymalizacji:

mysql -u[USERNAME] -p[PASSWORD] -Bse 'optimize tables [tables list]' [DB_NAME]

3

( MySQL Administrator(Część narzędzi GUI MySQL) może to zrobić na poziomie bazy danych.

Po prostu wybierz swój schemat i naciśnij Maintenanceprzycisk w prawym dolnym rogu.

Ponieważ narzędzia GUI osiągnęły status wycofania z eksploatacji, trudno je znaleźć na stronie mysql. Znaleziono je za pośrednictwem Google: http://dev.mysql.com/downloads/gui-tools/5.0.html

Nie wiem, czy nowy MySQL Workbench też to potrafi.

Możesz także użyć mysqlchecknarzędzia wiersza poleceń, które powinno być w stanie to zrobić.


2

Jeśli uzyskujesz bezpośredni dostęp do bazy danych, możesz napisać następujące zapytanie:

OPTIMIZE TABLE table1,table2,table3,table4......;

1

Ten skrypt bash zaakceptuje hasło roota jako opcję i zoptymalizuje je jeden po drugim, z wyjściem statusu:

#!/bin/bash

if [ -z "$1" ] ; then
  echo
  echo "ERROR: root password Parameter missing."
  exit
fi
MYSQL_USER=root
MYSQL_PASS=$1
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
TBLLIST=""
COMMA=""
SQL="SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE"
SQL="${SQL} table_schema NOT IN ('information_schema','mysql','performance_schema')"
for DBTB in `mysql ${MYSQL_CONN} -ANe"${SQL}"`
do
    echo OPTIMIZE TABLE "${DBTB};"
    SQL="OPTIMIZE TABLE ${DBTB};"
    mysql ${MYSQL_CONN} -ANe"${SQL}"
done

1

Skrypt startowy bash do wyświetlania listy i uruchamiania narzędzia przeciwko bazom danych ...

#!/bin/bash

declare -a dbs
unset opt

for each in $(echo "show databases;" | mysql -u root) ;do

        dbs+=($each)

done



echo " The system found [ ${#dbs[@]} ] databases." ;sleep 2
echo
echo "press 1 to run a check"
echo "press 2 to run an optimization"
echo "press 3 to run a repair"
echo "press 4 to run check,repair, and optimization"
echo "press q to quit"
read input

case $input in
        1) opt="-c"
        ;;
        2) opt="-o"
        ;;
        3) opt="-r"
        ;;
        4) opt="--auto-repair -c -o"
        ;;
        *) echo "Quitting Application .."; exit 7
        ;;
esac

[[ -z $opt ]] && exit 7;

echo " running option:  mysqlcheck $opt in 5 seconds  on all Dbs... "; sleep 5

for ((i=0; i<${#dbs[@]}; i++)) ;do
        echo "${dbs[$i]} : "
        mysqlcheck $opt ${dbs[$i]}  -u root
    done

0

moje 2 centy: zacznij od tabeli o największej fragmentacji

for table in `mysql -sss -e "select concat(table_schema,".",table_name) from information_schema.tables where table_schema not in ('mysql','information_schema','performance_schema') order by data_free desc;"
do
mysql -e "OPTIMIZE TABLE $table;"
done
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.