Tối ưu hóa MySQL tất cả các bảng?


245

MySQL có một lệnh TỐI ƯU HÓA có thể được sử dụng để lấy lại không gian chưa sử dụng trong bản cài đặt MySQL. Có cách nào (lệnh tích hợp hoặc thủ tục lưu trữ chung) để chạy tối ưu hóa này cho mọi bảng trong cơ sở dữ liệu và / hoặc cài đặt máy chủ, hay đây là thứ bạn phải tự viết kịch bản?


11
Hãy cẩn thận ở chỗ điều này sẽ không nhất thiết phải lấy lại không gian. Nếu bạn đang sử dụng InnoDB với một tệp duy nhất (có thể là thiết lập phổ biến nhất hiện nay) thay vì các tệp riêng biệt trên mỗi bảng, bạn vẫn sẽ sử dụng cùng một dung lượng đĩa ở cuối. Trong thực tế tôi đã thấy nó thực sự sử dụng nhiều dung lượng đĩa hơn khi tất cả đã được nói và thực hiện. Với các bảng lớn, bảng cũng có thể bị khóa trong một thời gian rất dài.
jmichalicek

1
OPTIMIZE TABLErất hữu ích cho MyISAM. Bây giờ Engine đó sẽ biến mất, nhu cầu OPTIMIZE TABLEsẽ không còn nữa, đặc biệt là cần định kỳ tối ưu hóa tất cả các bảng.
Rick James

+1 cho thông tin tốt - nhưng được cung cấp các thông lệ cơ sở dữ liệu trong thế giới thực tiêu chuẩn, tôi sẽ không ngạc nhiên nếu các bảng MyISAM cũ vẫn còn tồn tại trong một thập kỷ nữa
Alan Storm

Câu trả lời:


410

Bạn có thể sử dụng mysqlcheckđể làm điều này tại dòng lệnh.

Một cơ sở dữ liệu:

mysqlcheck -o <db_schema_name>

Tất cả các cơ sở dữ liệu:

mysqlcheck -o --all-databases

bạn có đề nghị lệnh này được lên lịch để chạy ít nhất mỗi tháng một lần không?
Gaia

11
Xin chào @Gaia. Không cần thiết. Tối ưu hóa tất cả các bảng trên một lịch trình nhất định không có lợi cho tất cả mọi người. Hãy xem bài đăng này và đọc các bình luận để suy nghĩ sâu hơn về chủ đề này hơn là tôi có thể cung cấp trong không gian hạn chế ở đây: xaprb.com/blog/2010/02/07/ trên
Ike Walker

18
sử dụng đơn giản:mysqlcheck -u [username] -p[password] -o [database name]
M Rostami

38
Xin lưu ý rằng các bảng bị khóa trong khi TỐI ƯU đang được thực hiện, việc này có thể mất nhiều thời gian nếu các bảng chứa nhiều dữ liệu. Vì vậy, trong thời gian một bảng đang được TỐI ƯU, không có bản ghi mới nào có thể được chèn hoặc xóa. Nói chung, tối ưu hóa tất cả các bảng của một hệ thống sản xuất có thể được coi là một hoạt động tầm thường.
Werner

2
@ No-Chip, bạn có thể tối ưu hóa các bảng trong máy khách MySQL bằng cách sử dụng OPTIMIZE TABLElệnh: dev.mysql.com/doc/refman/5.5/en/optizes-table.html . Ví dụ: tối ưu hóa một bảng như thế này : OPTIMIZE TABLE <your_schema>.<your_table>;, tối ưu hóa tất cả các bảng trong một lược đồ đã cho như thế này: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

Tôi đã tạo kịch bản 'đơn giản' này:

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;

Để chạy nó, chỉ cần dán nó vào bất kỳ IDE SQL nào được kết nối với cơ sở dữ liệu của bạn.

Lưu ý: mã này KHÔNG hoạt động trên phpmyadmin.

Làm thế nào nó hoạt động

Nó chạy một show tablestuyên bố và lưu trữ nó trong một tuyên bố chuẩn bị. Sau đó, nó chạy một optimize tabletrong bộ đã chọn.

Bạn có thể kiểm soát bảng nào để tối ưu hóa bằng cách đặt một giá trị khác trong var @tables_like(ví dụ set @tables_like = '%test%';:).


4
Môi trường lưu trữ được chia sẻ của tôi không có sẵn 'mysqlchk' vì vậy tôi có thể chạy nó trực tiếp từ phiên cuối 'mysql'. Cảm ơn bạn!
funwhilelost

Không có gì. Tôi sử dụng mã này để tối ưu hóa 50 cơ sở dữ liệu và dành thời gian tối thiểu nhất có thể. Nếu bạn nghĩ rằng tôi có thể cải thiện mã theo bất kỳ cách nào, hãy tiếp tục và cho tôi đề xuất của bạn. Tôi sẽ rất vui khi cải thiện đoạn mã quý giá này.
Ismael Miguel

Chuẩn bị bdtừ mã lỗi @b: 1064. Bạn có lỗi trong cú pháp SQL của mình; kiểm tra hướng dẫn tương ứng với phiên bản máy chủ MySQL của bạn để biết đúng cú pháp để sử dụng gần 'NULL' ở dòng 1
Paul Gregoire

@IsmaelMiguel đây là MySQL, câu trả lời của bạn sử dụng cú pháp TSQL và sẽ không hoạt động với MySQL.
Phrancis

2
@LorenzoBelfanti Cảm ơn bạn đã xác nhận nó. Tôi rất vui vì, thậm chí sau 2 năm, mã này hữu ích cho ít nhất là 10 người. Đó là một chiến thắng rất lớn đối với tôi! Cảm ơn bạn một lần nữa!
Ismael Miguel

20

Ví dụ sau tập lệnh php có thể giúp bạn tối ưu hóa tất cả các bảng trong cơ sở dữ liệu của bạn

<?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
Trên cơ sở dữ liệu có 200 bảng, bạn sẽ chạy 200 truy vấn riêng biệt tối ưu hóa 1 bảng mỗi lần. Bạn nên mã hóa tên bảng thành một chuỗi và do đó chỉ cần một truy vấn tối ưu hóa bảng.
Dean Marshall

8
Tôi tự hỏi nếu cách tiếp cận truy vấn riêng biệt đôi khi tốt hơn. MySQL cho biết các bảng bị khóa trong khi BẢNG TỐI ƯU đang chạy. Sau đó, có vẻ khôn ngoan hơn để tối ưu hóa từng cái một để cho phép máy chủ có được các khóa trong thời gian tối thiểu. Rõ ràng đó là cho một máy chủ tiếp tục được truy cập. Nếu không, thì tôi nghĩ rằng một truy vấn duy nhất là cách tiếp cận tốt nhất.
glarrain

Kịch bản sẽ trông như thế nào nếu bạn nổ tung và thực hiện thành 1 truy vấn? Cảm ơn.
H. Ferrence

8
@Dean Cách tiếp cận truy vấn riêng biệt thường tốt hơn để cung cấp phòng thở cho một ứng dụng trực tiếp. Trong thực tế, tôi thường thêm một độ trễ (chỉ 750ms hoặc hơn) cho chính xác mục đích đó.
zanlok

15

Thực hiện tất cả các quy trình cần thiết để sửa tất cả các bảng trong tất cả các cơ sở dữ liệu bằng tập lệnh shell đơn giản:

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

11

cho tất cả các cơ sở dữ liệu:

mysqlcheck -Aos -uuser -p 

Đối với một tối ưu hóa cơ sở dữ liệu:

mysqlcheck -os -uroot -p dbtest3

Ít nhất là đối với tôi, trong Linux, lệnh mysqlcheck -Aoskhông yêu cầu mật khẩu người dùng +.
Zuul

7

Từ phpMyAdmin và các nguồn khác bạn có thể sử dụng:

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>'

Sau đó, bạn có thể sao chép và dán kết quả vào một truy vấn mới hoặc thực hiện nó từ nguồn của riêng bạn. Nếu bạn không thấy toàn bộ tuyên bố: cách để xem toàn bộ tuyên bố trong phpmyadmin


đó là một câu trả lời hay, nhưng phpmyadmin của tôi không hiển thị toàn bộ lệnh, chỉ là những câu đầu tiên sau đó ... buồn cho tôi, lol.
MonneratRJ

6

Nếu bạn muốn phân tích, sửa chữa và tối ưu hóa tất cả các bảng trong tất cả các cơ sở dữ liệu trong máy chủ MySQL của mình, bạn có thể thực hiện việc này trong một lần từ dòng lệnh. Bạn sẽ cần root để làm điều đó mặc dù.

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

Khi bạn chạy nó, bạn sẽ được nhắc nhập mật khẩu root MySQL của bạn. Sau đó, nó sẽ bắt đầu và bạn sẽ thấy kết quả như nó đang xảy ra.

Ví dụ đầu ra:

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

Nếu bạn không biết mật khẩu gốc và đang sử dụng WHM, bạn có thể thay đổi mật khẩu từ bên trong WHM bằng cách truy cập: Trang chủ> Dịch vụ SQL> Mật khẩu gốc MySQL


5

Từ dòng lệnh:

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

sau đó nhập mật khẩu


4

Bạn có thể tối ưu hóa / kiểm tra và sửa chữa tất cả các bảng của cơ sở dữ liệu, sử dụng máy khách mysql.

Trước tiên, bạn nên lấy tất cả danh sách bảng, được phân tách bằng ',':

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

Bây giờ, khi bạn có tất cả các danh sách bảng để tối ưu hóa:

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

3

Các MySQL Administrator(một phần của MySQL GUI Tools) có thể làm điều đó cho bạn về mặt kĩ cơ sở dữ liệu.

Chỉ cần chọn lược đồ của bạn và nhấn Maintenancenút ở góc dưới bên phải.

Vì Công cụ GUI đã đạt đến trạng thái Cuối đời, chúng khó tìm thấy trên trang mysql. Tìm thấy chúng qua Google: http://dev.mysql.com/doads/gui-tools/5.0.html

Tôi không biết nếu MySQL Workbench mới cũng có thể làm điều đó.

Và bạn cũng có thể sử dụng mysqlcheckcông cụ dòng lệnh để có thể làm điều đó.


2

Nếu bạn đang truy cập cơ sở dữ liệu trực tiếp thì bạn có thể viết truy vấn sau:

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

1

Tập lệnh bash này sẽ chấp nhận mật khẩu gốc dưới dạng tùy chọn và tối ưu hóa từng cái một, với đầu ra trạng thái:

#!/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

Một tập lệnh bash khởi động để liệt kê và chạy một công cụ chống lại DB ...

#!/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

2cents của tôi: bắt đầu với bảng có độ phân mảnh cao nhất

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.