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ć?

Alan Storm
źródło
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
Ike Walker
źródło
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%';. :) .

Ismael Miguel
źródło
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());

   }
}

?>
Scherbius.com
źródło
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
Ivan Velkov
źródło
11

dla wszystkich baz danych:

mysqlcheck -Aos -uuser -p 

Dla jednej optymalizacji bazy danych:

mysqlcheck -os -uroot -p dbtest3
Muni
źródło
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

Szczery
źródło
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

Chris
źródło
5

Z linii poleceń:

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

następnie wpisz hasło

si le
źródł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]
Victor Driantsov
źródło
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ć.

Jürgen Steinblock
źródło
2

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

OPTIMIZE TABLE table1,table2,table3,table4......;
Anand agrawal
źródło
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
rubo77
źródło
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
Mike Q
źródło
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
DBHash.com
źródło