ค้นหาและแก้ไขตาราง MySQL แบบแยกส่วนได้อย่างไร


27

ฉันใช้ MySQLTuner ซึ่งชี้ให้เห็นว่าบางตารางมีการแยกส่วน ฉันใช้

mysqlcheck --optimize -A

เพื่อปรับตารางทั้งหมดให้เหมาะสม มันแก้ไขบางตาราง แต่ MySQLTuner ยังคงพบ 19 ตารางแยกส่วน ฉันจะดูตารางที่ต้องการจัดเรียงข้อมูลได้อย่างไร บางทีตาราง OPTIMIZE จะทำงานที่ mysqlcheck ไม่ได้? หรืออะไรที่ฉันควรลอง


1
ฉันมีปัญหาที่คล้ายกัน ฉันกำลังตั้งค่าฐานข้อมูลใหม่ด้วย MySQL 5.5 และตาราง InnoDB บางอย่างจะไม่ทำการแยกส่วน ฉันสงสัยว่าการตรวจสอบ Data_free (แสดงในคำตอบของ KayakJim) ไม่ถูกต้องกับตาราง InnoDB
docwhat

คำตอบ:


38

คำตอบสั้น ๆ :

select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

คำตอบ "คุณต้องรู้"

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

สิ่งนี้จะไม่ส่งผลต่อประสิทธิภาพเว้นแต่ว่าการแตกแฟรกเมนต์จะเพิ่มขึ้นมากเกินไป อะไรคือการกระจายตัวมากเกินไปเรามาดูข้อความค้นหาที่คุณต้องการ:

  select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

DATA_LENGTH และ INDEX_LENGTH เป็นพื้นที่ที่ข้อมูลและดัชนีของคุณกำลังใช้และ DATA_FREE คือจำนวนไบต์ทั้งหมดที่ไม่ได้ใช้ในหน้าตารางทั้งหมด (การกระจายตัว)

นี่คือตัวอย่างของตารางการผลิตจริง

| ENGINE | TABLE_NAME               | data_length | index_length | data_free |
| InnoDB | comments                 |         896 |          316 |         5 |

ในกรณีนี้เรามีตารางที่ใช้ (896 + 316) = 1212 MB และมีพื้นที่ว่าง 5 MB นี่หมายถึง "อัตราส่วนการกระจายตัว" ของ:

5/1212 = 0.0041

... อันไหนคือ "อัตราส่วนการกระจายตัวที่ต่ำมาก"

ฉันทำงานกับตารางที่มีอัตราส่วนใกล้กับ 0.2 (หมายถึง 20% ของช่องว่าง) และไม่เคยสังเกตคำสั่งที่ช้าลงแม้ว่าฉันปรับตารางให้เหมาะสมประสิทธิภาพก็เหมือนกัน แต่ใช้ตารางเพิ่มประสิทธิภาพบนตาราง 800MB ใช้เวลานานและบล็อกตารางเป็นเวลาหลายนาทีซึ่งไม่สามารถทำได้กับการผลิต

ดังนั้นหากคุณพิจารณาสิ่งที่คุณชนะในการแสดงและเวลาที่เสียไปกับการปรับตารางให้เหมาะสมฉันไม่ต้องการปรับให้เหมาะสม

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

และหากคุณปรับให้เหมาะสมการอัปเดตครั้งต่อไปจะสร้างช่องว่างโดยแบ่งหน้าเป็นสองหน้าขึ้นไป แต่การอัปเดตตารางที่กระจัดกระจายเร็วกว่าโต๊ะที่ไม่ได้แยกส่วนเพราะถ้าตารางมีการแยกส่วนการอัปเดตบนแถวไม่จำเป็นว่าจะต้องแยกหน้า

ฉันหวังว่านี่จะช่วยคุณได้


1
แม้ว่านี่จะเป็นคำตอบจากหลายปีที่ผ่านมา แต่ฉันคิดว่าฉันชี้ให้เห็นว่า data_free เป็นสถิติสำหรับพื้นที่ตารางทั้งหมดไม่ใช่สำหรับตารางที่เกี่ยวข้อง หากคุณเก็บหลายตารางไว้ด้วยกันในหนึ่ง tablespace data_free อาจทำให้คุณเข้าใจผิดว่าเชื่อว่าตารางนั้นต้องการการจัดเรียงข้อมูลเมื่อมันหมายถึงว่ามี extents ว่างใน tablespace การเรียกใช้ตารางการปรับให้เหมาะสมจะไม่ลดส่วนที่ฟรี การจัดเรียงข้อมูลบนโต๊ะอาจเพิ่มพื้นที่ว่างได้
Bill Karwin

14

เพียงเพิ่มคำตอบจากFelipe-Rojasคุณสามารถคำนวณอัตราส่วนส่วนที่เป็นส่วนหนึ่งของแบบสอบถาม:

select ENGINE,
  concat(TABLE_SCHEMA, '.', TABLE_NAME) as table_name,
  round(DATA_LENGTH/1024/1024, 2) as data_length,
  round(INDEX_LENGTH/1024/1024, 2) as index_length,
  round(DATA_FREE/1024/1024, 2) as data_free,
  (data_free/(index_length+data_length)) as frag_ratio
FROM information_schema.tables
WHERE DATA_FREE > 0
ORDER BY frag_ratio DESC;

หากตารางมีการแยกส่วนเล็ก ๆ น้อย ๆ (น้อยกว่า 5%?) คุณอาจปล่อยให้อยู่คนเดียว

สิ่งใดที่ใหญ่กว่าและคุณจะต้องประเมินตามการใช้งานฐานข้อมูลของคุณการล็อคตารางเป็นต้นว่าการจัดเรียงข้อมูลในตารางมีความสำคัญเพียงใด


2

Optimize Table จะแก้ไขปัญหาที่คุณประสบอยู่

หากคุณมีฐานข้อมูลเพียงเล็กน้อยคุณสามารถใช้ PHPMyAdmin เพื่อดูฐานข้อมูลทั้งหมดของคุณ เลือกตารางที่มีโอเวอร์เฮดจากนั้นเลือกเพื่อปรับให้เหมาะสม

หากคุณมีฐานข้อมูลจำนวนมากดังนั้นวิธีอื่นน่าจะเหมาะสมกว่า

ฉันใช้การตั้งค่าสคริปต์ PHP ต่อไปนี้ใน cron เพื่อให้ทำงานทุกชั่วโมง

$DB = new mysqli ('localhost', 'DbUser', 'DbPassword');
$results = $DB->query('show databases');
$allDbs = array();
while ($row = $results->fetch_array(MYSQLI_NUM))
{
    $allDbs[] = $row[0];
}
$results->close();
foreach ($allDbs as $dbName)
{
    if ($dbName != 'information_schema' && $dbName != 'mysql')
    {
        $DB->select_db($dbName);
        $results = $DB->query('SHOW TABLE STATUS WHERE Data_free > 0');
        if ($results->num_rows > 0)
        {
            while ($row = $results->fetch_assoc())
            {
                $DB->query('optimize table ' . $row['Name']);
            }
        }
        $results->close();
    }
}
$DB->close();

3
ฉันค่อนข้างแน่ใจว่าmysqlcheck --optimize -Aเป็นเช่นเดียวกับ SQLOPTIMIZE TABLE <tablename>;
docwhat

2

ฉันเจอหน้านี้และพบคำค้นหาโดย Felipe-Rojas และ sysadmiral ว่ามีประโยชน์มาก แต่ในกรณีของฉันฉันใช้การสืบค้นใน phpMyAdmin ของ WHM และการได้รับเฉพาะ TABLE_NAME ไม่เป็นประโยชน์เนื่องจากฐานข้อมูลไม่ได้อยู่ในรายการและฐานข้อมูลหลายแห่งมีชื่อตารางเดียวกัน ดังนั้นการเพิ่มTABLE_SCHEMAจะให้คอลัมน์นั้นเช่นกัน

select  ENGINE, TABLE_SCHEMA, TABLE_NAME, Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free, (data_free/(index_length+data_length)) as frag_ratio from information_schema.tables  where  DATA_FREE > 0 order by frag_ratio desc

แสดงให้เห็นถึงฐานข้อมูล

ENGINE  | TABLE_SCHEMA  | TABLE_NAME    | data_length   | index_length  | data_free | frag_ratio

InnoDB  | db_name       | db_table      | 0             | 0             | 8         | 170.6667

หากต้องการ "แก้ไข" ฉันใช้ลิงก์ตารางจัดเรียงข้อมูลใน phpMyAdmin สำหรับแต่ละตารางที่ทำให้ "frag_ratio" สูงซึ่ง phpMyAdmin ดำเนินการ:

ALTER TABLE `table_name` ENGINE = InnoDB;

0

ตารางการใช้ของ MySQL InnoDB OPTIMIZEdเครื่องยนต์หลักไม่เคยจะต้อง

ค่าของData_freeจากinformation_schema.tablesหรือSHOW TABLE STATUSมักจะไม่เป็นศูนย์มากถึงแม้ว่าคุณคิดว่าคุณได้ทำทุกสิ่งที่คุณสามารถทำ defrag ตารางของคุณ นอกจากนี้เมตริกนั้นเป็นเพียงหนึ่งในหลาย ๆแฟรกเมนต์ที่สามารถเกิดขึ้นได้ (นอกจากนี้ยังเสียพื้นที่ในบล็อกยกเลิกรายการดัชนี BTrees เทียบกับข้อมูล BTrees ฯลฯ ฯลฯ

และinnodb_file_per_tableทำให้การใช้งานData_freeยุ่งยากขึ้น หากตารางอยู่ในibdata1นั้นData_freeหมายถึงพื้นที่ตารางทั้งหมด จำนวนค่อนข้างไร้ประโยชน์ หากตารางอยู่ใน.ibdไฟล์ของตัวเองมันอาจจะมีขนาดไม่กี่ MB หรือไม่กี่เปอร์เซ็นต์ของขนาดตารางแล้วแต่จำนวนใดจะใหญ่กว่า

แต่ถ้าคุณได้ลบจำนวนมากของแถวและไม่ได้ตั้งใจที่จะเติมตารางอาจOPTIMIZE TABLEมันจะคุ้มค่าการทำงาน

PARTITIONsยังแสดงจำนวนรบกวนData_freeเนื่องจากแต่ละพาร์ติชันมักจะแสดง 4-7MB "ฟรี" และสิ่งนี้จะไม่หายไป

ทำไมต้องจัดเรียงข้อมูล

  • หากต้องการคืนพื้นที่ให้กับระบบปฏิบัติการ ดีคุณอาจจะประสบความสำเร็จในเวลาสั้น ๆ innodb_file_per_table=1นี้ถ้าคุณมี แต่เมื่อคุณเพิ่มแถวคุณจะนำมันกลับมาจากระบบปฏิบัติการ
  • เพื่อเพิ่มความเร็วในการเข้าถึง? ลืมมันไปเถอะ เลย์เอาต์ของบล็อกบนดิสก์นั้นค่อนข้างสุ่มและเป็นช่วงสองสามทศวรรษที่ผ่านมา ครึ่งศตวรรษที่ผ่านมามันค่อนข้างสำคัญที่จะจัดเรียงบล็อกใหม่
  • เพื่อปรับสมดุล BTrees? ดังนั้น? พวกเขาจะกลายเป็นไม่สมดุลอีกครั้งทันที steady-state สำหรับ BTrees ที่ถูกสุ่มเข้าไปคือ 69% Data_freeและไม่ได้มีปัจจัยยังเป็น
  • MySQLTuner พูดว่าอย่างไร? ผลิตภัณฑ์นั้นต้องทำใจให้สบาย

บันทึกประวัติ เมื่อฉันได้ช่วยให้ DBAs กับตาราง MyISAM ส่วนใหญ่ที่ผมค้นพบอาจจะเป็น 2 จาก 1,000 ตารางที่ถูกช่วยโดยรายเดือน OPTIMIZEตั้งแต่นั้นมาผมได้ทำงานร่วมกับหลายพันตาราง InnoDB, OPTIMIZEยังพบปัญหาประสิทธิภาพการทำงานที่มีแนวโน้มที่จะได้รับความช่วยเหลือจาก (แน่นอนว่ามีปัญหาเกี่ยวกับพื้นที่ดิสก์ที่OPTIMIZEอาจช่วยได้ แต่นั่นก็เป็นเรื่องยุ่งยาก - โดยปกติ DBA จะมีพื้นที่ดิสก์ไม่เพียงพอที่จะทำงานOPTIMIZE!)

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