MySQL ปรับตารางทั้งหมดได้หรือไม่


245

MySQL มีคำสั่งOPTIMIZE TABLEซึ่งสามารถใช้เพื่อเรียกคืนพื้นที่ที่ไม่ได้ใช้ในการติดตั้ง MySQL มีวิธี (คำสั่งในตัวหรือขั้นตอนการจัดเก็บทั่วไป) เพื่อเรียกใช้การเพิ่มประสิทธิภาพนี้สำหรับทุกตารางในฐานข้อมูลและ / หรือการติดตั้งเซิร์ฟเวอร์หรือเป็นสิ่งที่คุณต้องสคริปต์ด้วยตัวเอง?


11
ระวังด้วยว่าการทำเช่นนี้จะไม่เรียกคืนพื้นที่ หากคุณกำลังใช้ InnoDB ด้วยไฟล์เดียว (อาจเป็นการตั้งค่าที่พบบ่อยที่สุดในปัจจุบัน) แทนที่จะแยกไฟล์ต่อตารางคุณจะยังคงใช้พื้นที่ดิสก์จำนวนเท่าเดิมในตอนท้าย อันที่จริงฉันเห็นแล้วว่ามันใช้พื้นที่ดิสก์มากขึ้นอย่างมากเมื่อทุกคนพูดและทำ ด้วยตารางขนาดใหญ่ตารางอาจถูกล็อกเป็นเวลานานเช่นกัน
jmichalicek

1
OPTIMIZE TABLEมีประโยชน์สำหรับ MyISAM ตอนนี้เครื่องยนต์กำลังจะหายไปความต้องการOPTIMIZE TABLEกำลังจะหายไปโดยเฉพาะอย่างยิ่งความจำเป็นที่จะต้องปรับตารางทั้งหมดให้เหมาะสมเป็นระยะ
Rick James

+1 สำหรับข้อมูลที่ดี rick - แต่จากมาตรฐานการปฏิบัติฐานข้อมูลโลกแห่งความจริงฉันจะไม่แปลกใจถ้าตาราง MyISAM เก่ายังคงอยู่รอบ ๆ อีกสิบปี
Alan Storm

คำตอบ:


410

คุณสามารถใช้mysqlcheckทำสิ่งนี้ได้ที่บรรทัดคำสั่ง

ฐานข้อมูลเดียว:

mysqlcheck -o <db_schema_name>

ฐานข้อมูลทั้งหมด:

mysqlcheck -o --all-databases

คุณจะแนะนำคำสั่งนี้ให้กำหนดเวลาให้ทำงานอย่างน้อยเดือนละครั้งหรือไม่
Gaia

11
สวัสดี @Gaia ไม่จำเป็น. การปรับตารางทั้งหมดให้เหมาะสมตามกำหนดเวลานั้นไม่เป็นประโยชน์สำหรับทุกคน ลองดูที่โพสต์นี้และอ่านความคิดเห็นสำหรับความคิดเชิงลึกในหัวข้อนี้มากกว่าที่ฉันสามารถให้ในพื้นที่ จำกัด ได้ที่นี่: xaprb.com/blog/2010/02/07/…
Ike Walker

18
ใช้งานง่าย:mysqlcheck -u [username] -p[password] -o [database name]
M Rostami

38
โปรดทราบว่าตารางจะถูกล็อคในขณะที่กำลังดำเนินการ OPTIMIZE ซึ่งอาจใช้เวลานานพอสมควรหากตารางมีข้อมูลจำนวนมาก ดังนั้นในช่วงเวลาที่ตารางกำลังถูกปรับให้เหมาะสมไม่มีบันทึกใหม่ที่สามารถแทรกหรือลบได้ โดยทั่วไปการเพิ่มประสิทธิภาพของตารางทั้งหมดของระบบการผลิตไม่สามารถพิจารณาได้ว่าเป็นการดำเนินการที่ไม่สำคัญ
เวอร์เนอร์

2
@ ไม่มีชิปคุณสามารถเพิ่มประสิทธิภาพในตารางลูกค้า MySQL โดยใช้OPTIMIZE TABLEคำสั่ง: dev.mysql.com/doc/refman/5.5/en/optimize-table.html ตัวอย่างเช่นเพิ่มประสิทธิภาพหนึ่งตารางเช่นนี้: OPTIMIZE TABLE <your_schema>.<your_table>;เพิ่มประสิทธิภาพของตารางทั้งหมดในสคีมาที่กำหนดเช่นนี้: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

ฉันทำสคริปต์ 'ง่าย' นี้:

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;

ในการรันเพียงวางใน SQL IDE ใด ๆ ที่เชื่อมต่อกับฐานข้อมูลของคุณ

แจ้งให้ทราบล่วงหน้า: รหัสนี้จะไม่ทำงานบน phpmyadmin

มันทำงานอย่างไร

มันรันshow tablesคำสั่งและเก็บไว้ในคำสั่งที่เตรียมไว้ จากนั้นจะรัน a optimize tableในชุดที่เลือก

คุณสามารถควบคุมตารางเพื่อเพิ่มประสิทธิภาพโดยการตั้งค่าที่แตกต่างกันในวา@tables_like(เช่นset @tables_like = '%test%';)


4
สภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกันของฉันไม่มี 'mysqlchk' อยู่ดังนั้นฉันสามารถเรียกใช้งานได้โดยตรงจากเซสชันเทอร์มินัล 'mysql' ขอบคุณ!
funwhilelost

ยินดี. ฉันใช้รหัสนี้เพื่อปรับฐานข้อมูลให้เหมาะสม 50 ฐานและใช้เวลาน้อยที่สุดเท่าที่จะทำได้ หากคุณคิดว่าฉันสามารถปรับปรุงรหัสได้ไม่ว่าทางใดก็ตามไปข้างหน้าและให้คำแนะนำกับฉัน ฉันยินดีที่จะปรับปรุงโค้ดที่มีค่านี้
Ismael Miguel

จัดทำbdจาก @b รหัสข้อผิดพลาด: 1064 คุณมีข้อผิดพลาดในไวยากรณ์ SQL ของคุณ; ตรวจสอบคู่มือที่สอดคล้องกับรุ่นเซิร์ฟเวอร์ MySQL ของคุณสำหรับไวยากรณ์ที่ถูกต้องเพื่อใช้ใกล้กับ 'NULL' ที่บรรทัดที่ 1
Paul Gregoire

@IsmaelMiguel นี่คือ MySQL คำตอบของคุณใช้ไวยากรณ์ TSQL และจะไม่ทำงานกับ MySQL
Phrancis

2
@ LorenzoBelfanti ขอบคุณที่ยืนยันมัน ฉันดีใจมากที่หลังจาก 2 ปีรหัสนี้มีประโยชน์อย่างน้อย 10 คน นั่นคือชัยชนะที่ยิ่งใหญ่สำหรับฉัน! ขอขอบคุณอีกครั้ง!
Ismael Miguel

20

ตัวอย่างต่อไปนี้สคริปต์ PHP สามารถช่วยให้คุณเพิ่มประสิทธิภาพตารางทั้งหมดในฐานข้อมูลของคุณ

<?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
บนฐานข้อมูลที่มี 200 ตารางคุณจะเรียกใช้การค้นหาแยกต่างหาก 200 แบบสอบถามการปรับให้เหมาะสมครั้งละ 1 ตาราง คุณควรเชื่อมโยงชื่อตารางเป็นหนึ่งสตริงและด้วยเหตุนี้จึงจำเป็นต้องใช้แบบสอบถามตารางเพิ่มประสิทธิภาพเดียวเท่านั้น
คณบดีมาร์แชลล์

8
ฉันสงสัยว่าวิธีสืบค้นแบบแยกบางครั้งดีกว่าหรือไม่ MySQL บอกว่าตารางนั้นถูกล็อคขณะที่ OPTIMIZE TABLE กำลังทำงานอยู่ ดูเหมือนว่าฉลาดในการเพิ่มประสิทธิภาพแต่ละครั้งเพื่อให้เซิร์ฟเวอร์ได้รับการล็อคในเวลาต่ำสุด เห็นได้ชัดว่ามีไว้สำหรับเซิร์ฟเวอร์ที่ถูกทำให้เข้าถึงได้ ถ้าไม่เช่นนั้นฉันคิดว่าข้อความค้นหาเดียวเป็นวิธีที่ดีที่สุด
Glarrain

สคริปต์จะมีลักษณะอย่างไรหากคุณกำหนดและสร้างเป็น 1 ข้อความค้นหา ขอบคุณ
H. Ferrence

8
@Dean วิธีการสืบค้นแยกต่างหากมักจะดีกว่าที่จะให้ห้องหายใจสำหรับแอปพลิเคชันสด อันที่จริงฉันมักจะเพิ่มความล่าช้า (เพียง 750ms หรือมากกว่านั้น) เพื่อจุดประสงค์นั้น
zanlok

15

ทำโพรซีเดอร์ที่จำเป็นทั้งหมดสำหรับการแก้ไขตารางทั้งหมดในฐานข้อมูลทั้งหมดด้วยเชลล์สคริปต์อย่างง่าย:

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

11

สำหรับฐานข้อมูลทั้งหมด:

mysqlcheck -Aos -uuser -p 

สำหรับการปรับฐานข้อมูลเดียว:

mysqlcheck -os -uroot -p dbtest3

อย่างน้อยที่สุดสำหรับฉันภายใต้ Linux คำสั่งmysqlcheck -Aosไม่ต้องการชื่อผู้ใช้ + รหัสผ่าน
Zuul

7

จาก phpMyAdmin และแหล่งข้อมูลอื่นคุณสามารถใช้:

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

จากนั้นคุณสามารถคัดลอกและวางผลลัพธ์ไปยังแบบสอบถามใหม่หรือเรียกใช้จากแหล่งที่มาของคุณเอง หากคุณไม่เห็นข้อความทั้งหมด: วิธีดูข้อความทั้งหมดใน phpmyadmin


นั่นเป็นคำตอบที่ดี แต่ phpmyadmin ของฉันไม่แสดงคำสั่งทั้งหมดเพียงคำสั่งแรกแล้ว ... น่าเศร้าสำหรับฉันฮ่า ๆ
MonneratRJ

6

หากคุณต้องการวิเคราะห์ซ่อมแซมและปรับแต่งตารางทั้งหมดในฐานข้อมูลทั้งหมดในเซิร์ฟเวอร์ MySQL ของคุณคุณสามารถทำได้ในครั้งเดียวจากบรรทัดคำสั่ง คุณจะต้องรูทเพื่อทำสิ่งนั้น

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

เมื่อคุณเรียกใช้งานคุณจะได้รับแจ้งให้ป้อนรหัสผ่านรูทของ MySQL หลังจากนั้นระบบจะเริ่มและคุณจะเห็นผลลัพธ์เมื่อเกิดขึ้น

ตัวอย่างผลลัพธ์:

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

หากคุณไม่ทราบรหัสผ่านรูทและใช้ WHM คุณสามารถเปลี่ยนได้จากภายใน WHM โดยไปที่: หน้าหลัก> บริการ SQL> รหัสผ่าน root ของ MySQL


5

จากบรรทัดคำสั่ง:

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

จากนั้นพิมพ์รหัสผ่าน


4

คุณสามารถปรับให้เหมาะสม / ตรวจสอบและซ่อมแซมตารางฐานข้อมูลทั้งหมดโดยใช้ไคลเอนต์ mysql

ก่อนอื่นคุณควรรับรายการตารางทั้งหมดคั่นด้วย ',':

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

ตอนนี้เมื่อคุณมีรายการตารางทั้งหมดสำหรับการปรับให้เหมาะสม:

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

3

MySQL Administrator(ส่วนหนึ่งของเครื่องมือ MySQL GUI) สามารถทำเพื่อคุณในระดับฐานข้อมูล

เพียงเลือกสคีมาของคุณแล้วกดMaintenanceปุ่มที่มุมล่างขวา

เนื่องจากเครื่องมือ GUI ได้สถานะสิ้นสุดอายุการใช้งานจึงหาได้ยากในหน้า mysql พบพวกเขาผ่าน Google: http://dev.mysql.com/downloads/gui-tools/5.0.html

ฉันไม่รู้ว่า MySQL Workbench ใหม่สามารถทำเช่นนั้นได้หรือไม่

และคุณสามารถใช้mysqlcheckเครื่องมือบรรทัดคำสั่งซึ่งควรทำเช่นนั้นได้เช่นกัน


2

หากคุณกำลังเข้าถึงฐานข้อมูลโดยตรงคุณสามารถเขียนแบบสอบถามต่อไปนี้:

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

1

สคริปต์ทุบตีนี้จะยอมรับรหัสผ่านรูทเป็นตัวเลือกและปรับให้เหมาะสมทีละตัวโดยมีสถานะออก:

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

สคริปต์ทุบตีเริ่มต้นเพื่อแสดงรายการและเรียกใช้เครื่องมือกับ DBs ...

#!/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 ของฉัน: เริ่มต้นด้วยตารางที่มีการกระจายตัวสูงสุด

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.