วิธีการประมาณ / ทำนายขนาดข้อมูลและขนาดดัชนีของตารางใน MySQL


26

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

ตัวอย่างเช่นเรามีตาราง City พร้อมกับเครื่องยนต์ InnoDBสมมติว่าในอนาคต (ในอีก 1 ปีข้างหน้า) จะมี 1 ล้านระเบียนดังนั้นสิ่งที่จะเป็นขนาดข้อมูลโดยประมาณและขนาดดัชนีของตารางนั้นในช่วงเวลานี้

mysql> desc City;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| ID          | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name        | char(35) | NO   |     |         |                |
| CountryCode | char(3)  | NO   | MUL |         |                |
| District    | char(20) | NO   |     |         |                |
| Population  | int(11)  | NO   |     | 0       |                |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.03 sec)

UPDATE

สิ่งที่จะเป็นขอบเขตบนโดยประมาณ (ขนาดสูงสุดของตาราง) ที่มี 1 ล้านบันทึกและเราจะประมาณได้อย่างไร


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

คำตอบ:


51

รับคำอธิบายตารางที่ฉันเห็น

  • 66 ไบต์ต่อแถวของข้อมูล
  • 4 ไบต์ต่อแถวสำหรับคีย์หลัก
  • 7 ไบต์ต่อแถวสำหรับดัชนีรหัสประเทศ
    • 3 ไบต์สำหรับประเทศ
    • 4 ไบต์สำหรับคีย์คลัสเตอร์ที่แนบกับรหัสประเทศ
  • จำนวนข้อมูลและคีย์ทั้งหมด 77 ไบต์
  • สิ่งนี้ไม่ได้แยกประเภทการดูแลทำความสะอาดสำหรับ BTREEs หรือ Tablespace Fragmentation

สำหรับหนึ่งล้านแถวนั่นจะเป็น 77,000,000 ไบต์ (73.43 MB)

สำหรับการวัดตารางสำหรับ mydb.mytable ตารางที่กำหนดคุณสามารถเรียกใช้แบบสอบถามนี้

SELECT 
    CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',SUBSTR(units,pw1*2+1,2)) DATSIZE,
    CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',SUBSTR(units,pw2*2+1,2)) NDXSIZE,
    CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',SUBSTR(units,pw3*2+1,2)) TBLSIZE
FROM
(
    SELECT DAT,NDX,TBL,IF(px>4,4,px) pw1,IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3
    FROM 
    (
        SELECT data_length DAT,index_length NDX,data_length+index_length TBL,
        FLOOR(LOG(IF(data_length=0,1,data_length))/LOG(1024)) px,
        FLOOR(LOG(IF(index_length=0,1,index_length))/LOG(1024)) py,
        FLOOR(LOG(data_length+index_length)/LOG(1024)) pz
        FROM information_schema.tables
        WHERE table_schema='mydb'
        AND table_name='mytable'
    ) AA
) A,(SELECT 'B KBMBGBTB' units) B;

ในการวัดตารางทั้งหมดจัดกลุ่มตามฐานข้อมูลและเครื่องมือจัดเก็บข้อมูล

SELECT
    IF(ISNULL(DB)+ISNULL(ENGINE)=2,'Database Total',
    CONCAT(DB,' ',IFNULL(ENGINE,'Total'))) "Reported Statistic",
    LPAD(CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',
    SUBSTR(units,pw1*2+1,2)),17,' ') "Data Size",
    LPAD(CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',
    SUBSTR(units,pw2*2+1,2)),17,' ') "Index Size",
    LPAD(CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',
    SUBSTR(units,pw3*2+1,2)),17,' ') "Total Size"
FROM
(
    SELECT DB,ENGINE,DAT,NDX,TBL,
    IF(px>4,4,px) pw1,IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3
    FROM 
    (SELECT *,
        FLOOR(LOG(IF(DAT=0,1,DAT))/LOG(1024)) px,
        FLOOR(LOG(IF(NDX=0,1,NDX))/LOG(1024)) py,
        FLOOR(LOG(IF(TBL=0,1,TBL))/LOG(1024)) pz
    FROM
    (SELECT
        DB,ENGINE,
        SUM(data_length) DAT,
        SUM(index_length) NDX,
        SUM(data_length+index_length) TBL
    FROM
    (
       SELECT table_schema DB,ENGINE,data_length,index_length FROM
       information_schema.tables WHERE table_schema NOT IN
       ('information_schema','performance_schema','mysql')
       AND ENGINE IS NOT NULL
    ) AAA GROUP BY DB,ENGINE WITH ROLLUP
) AAA) AA) A,(SELECT ' BKBMBGBTB' units) B;

เรียกใช้คิวรีเหล่านี้และคุณสามารถติดตามการเปลี่ยนแปลงในการใช้ดิสก์ฐานข้อมูล / โปรแกรม

ให้มันลอง !!!


1
นี่เป็นแบบสอบถามที่ยอดเยี่ยมสำหรับการดูขนาดตารางทั้งหมดของคุณ
ghayes

CHARยาวจะต้องมีการคูณด้วย 3 CHARSET utf8ถ้าคุณมี ค่าใช้จ่ายทั้งหมดสามารถประเมินได้โดยการคำนวณสองเท่าหรือสามเท่า
Rick James

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

@ceinmart innodb_page_size ได้รับการแก้ไข (16K หรือ 16384 โดยค่าเริ่มต้น) และกลายเป็นขอบเขตที่แถวและจัดกลุ่มหรือแยก การเปลี่ยน innodb_page_size สามารถแก้ไขการจัดเก็บข้อมูลสำหรับดีหรือไม่ดีขึ้นอยู่กับว่าแถวเต็มหรือกระจัดกระจาย (โดยเฉพาะอย่างยิ่งกับการมี TEXT / BLOB / VARCHAR) ที่ดีที่สุดคุณควรเปรียบเทียบขนาดของไฟล์. ibd กับสคีมาที่รายงานเพื่อประเมินอัตราส่วน คุณอาจต้องดำเนินการ NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;) เพื่อให้ได้อัตราส่วนที่ถูกต้อง ความพยายามอาจไม่คุ้มค่า
RolandoMySQLDBA

@ceinmart โปรดจำไว้ว่าการเปลี่ยนหมวก innodb_page_size ไม่ใช่การตั้งค่าแบบตารางต่อตาราง คุณจะต้องทำการส่งออกข้อมูลแบบเต็ม (ดูmariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA

4

หากคุณกำลังใช้ตาราง InnoDB คุณสามารถรับขนาดสำหรับข้อมูล / ดัชนีแต่ละรายการmysql.innodb_index_statsได้ ว่า 'ขนาด' สถิติมีคำตอบในหน้าดังนั้นคุณต้องคูณด้วยหน้าขนาดที่เป็น 16K โดยค่าเริ่มต้น

select database_name, table_name, index_name, stat_value*@@innodb_page_size
from mysql.innodb_index_stats where stat_name='size';

ดัชนีหลักคือข้อมูลตัวเอง


1
สิ่งนี้จะถือว่าคุณมีข้อมูลในตาราง ดูเหมือนว่า OP ต้องการประมาณการก่อนการเติมข้อมูล
Rick James

0
SELECT  Table_NAME "tablename",
           data_length   "table data_length in Bytes",
           index_length  "table index_length in Bytes",
           data_free  "Free Space in Bytes"
    FROM  information_schema.TABLES  where  Table_schema = 'databasename';

โดยการดำเนินการแบบสอบถามนี้คุณจะได้รับขนาดที่ใช้สำหรับDataและIndexของตารางคุณสามารถตรวจสอบขนาดนี้กับ # ของแถวและทำนาย 1 ล้านแถว


1
ฉันไม่แน่ใจ แต่สิ่งนี้จะให้ผลลัพธ์ที่ถูกต้องหรือไม่ คุณเคยทดสอบสิ่งนี้หรือไม่?
Abdul Manaf

ที่จริงฉันกำลังทดสอบผลการค้นหานี้เป็นระยะเพื่อดูขนาดการเติบโต (%) wrt
Peter Venderberghe

0

หากคุณยังไม่มีข้อมูลต่อไปนี้เป็นเคล็ดลับ ข้อมูลต่อไปนี้ใช้กับ InnoDB (MyISAM ง่ายกว่าและเล็กกว่ามาก)

อย่าใช้CHARสำหรับคอลัมน์ที่มีความยาวผันแปรได้ สิ่งที่CHARACTER SETคุณกำลังใช้? Ascii ต้องการหนึ่งไบต์ต่ออักขระ utf8mb4 ต้องการระหว่าง 1 และ 4

4 bytes per INT
35 for CHAR(35), if ascii or latin1; varchar is probably less
3 for the country code; it is fixed length
etc

รวม = ประมาณ 80 ไบต์

คูณ 80 ด้วยระหว่าง 2 และ 3 เพื่อคิดค่าใช้จ่ายต่าง ๆ ส่วนใหญ่แล้วตารางแถว 1M จะอยู่ระหว่าง 160MB ถึง 240MB

หากต้องการวัดดัชนีเดียวให้พูดได้CountryCode3 ไบต์:

3 bytes data
4 bytes for the PK (implicitly included with any secondary key)
25 bytes basic overhead
32 total
times 1.5 -- overhead for BTree that was randomly inserted into
48MB -- total for 1M rows.

หมายเหตุ:

  • ต้องคำนวณโหนดใบไม้ (ของ BTrees) เท่านั้น โอเวอร์เฮดสำหรับโหนดที่ไม่ใช่แบบลีฟมักเป็น1%

  • PRIMARY KEYคือ "คลัสเตอร์" กับข้อมูลจึงมีความจำเป็นที่จะต้องคำนวณมัน

  • หากคุณไม่มี PK ชัดเจนคุณต้องเพิ่ม 6 ไบต์ให้กับขนาดแถวเพื่ออนุญาต PK ประดิษฐ์

  • ROW_FORMAT = COMPRESSEDช่วยให้คุณมีการหดตัว 2: 1 (สิ่งนี้ไม่ดีเท่าอัตราการบีบอัดทั่วไป (ฯลฯ ) ของ 3: 1)

  • SHOW TABLE STATUS LIKE "tablename";เป็นวิธีที่รวดเร็วในการคำนวณขนาด 'จริง' ดูData_lengthข้อมูลและ PK; Index_lengthสำหรับดัชนีรองและData_freeอื่น ๆ

  • มันเป็นเรื่องยากสำหรับเกินIndex_length Data_lengthอย่างไรก็ตามมันไม่ใช่ "ผิด" ที่จะเกิดขึ้น


-1

มันน่าเบื่อ แต่มีรายละเอียดในเอกสาร

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

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

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