Cara memperkirakan / memprediksi ukuran data dan ukuran indeks suatu tabel di MySQL

26

Saya menemukan apa cara terbaik untuk memperkirakan ukuran tabel untuk itu saya telah mempelajari banyak blog dan forum tetapi tidak dapat menemukan jawaban yang akurat

Sebagai contoh kita memiliki tabel City dengan mesin InnoDB , katakanlah di masa depan (dalam 1 tahun mendatang) itu akan memiliki 1 juta catatan sehingga apa yang akan menjadi ukuran data yang diperkirakan dan ukuran indeks dari tabel itu dalam periode ini.

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)

MEMPERBARUI

Apa yang akan menjadi batas atas yang diestimasi (ukuran tabel maksimum) dengan 1 juta catatan dan bagaimana kita dapat memperkirakannya.

Abdul Manaf
sumber
Ini bagus. tetapi apakah mungkin untuk mendapatkan kolom ukuran indeks bijaksana. Yang dimaksud adalah jika Anda memiliki tabel dengan (katakanlah) 5 kolom diindeks. Bisakah kita mendapatkan ukuran indeks masing-masing? Saya akan menanyakan ini sebagai pertanyaan lain. terima kasih
Sushil

Jawaban:

51

Diberikan deskripsi tabel, saya melihat

  • 66 byte per baris data
  • 4 byte per baris untuk kunci utama
  • 7 byte per baris untuk indeks kode negara
    • 3 byte untuk negara
    • 4 byte untuk Clustered Key yang terlampir pada kode negara
  • Total 77 byte data dan kunci
  • Ini tidak memperhitungkan pembersihan untuk BTREE atau Tablespace Fragmentation

Untuk satu juta baris, itu akan menjadi 77.000.000 byte (73,43 MB)

Adapun untuk mengukur tabel, untuk tabel yang diberikan mydb.mytable, Anda dapat menjalankan kueri ini

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;

Untuk mengukur semua tabel yang dikelompokkan berdasarkan Database dan Storage Engine

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;

Jalankan pertanyaan ini dan Anda dapat melacak perubahan dalam penggunaan disk database / mesin.

Cobalah !!!

RolandoMySQLDBA
sumber
1
Ini adalah permintaan yang sangat bagus untuk melihat semua ukuran tabel Anda.
ghayes
The CHARpanjang perlu dikalikan dengan 3 jika Anda memiliki CHARSET utf8. Seluruh overhead dapat diperkirakan dengan menggandakan atau melipattigakan perhitungan.
Rick James
@RolandoMySQLDBA, apakah Anda tahu apakah mungkin untuk menghitung ukuran baris "nyata" dari sebuah tabel dengan tujuan untuk membandingkan dengan ukuran sebenarnya (tabel terkompresi) dan mendapatkan rasio kompres?
ceinmart
@ceinmart innodb_page_size diperbaiki (16K atau 16384 secara default) dan menjadi batas tempat baris dan dikelompokkan atau dibagi. Mengubah innodb_page_size dapat mengubah penyimpanan data baik atau buruk. Berdasarkan seberapa diisi atau jarangnya baris (terutama dengan keberadaan TEXT / BLOB / VARCHAR). Paling-paling, Anda harus membandingkan ukuran file .ibd dengan apa yang dilaporkan skema untuk memperkirakan rasio. Anda mungkin juga perlu melakukan NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;) untuk mendapatkan rasio yang akurat. Upaya mungkin tidak sepadan.
RolandoMySQLDBA
@ceinmart Ingatlah bahwa mengubah innodb_page_size bukanlah pengaturan tabel-per-tabel. Anda perlu melakukan ekspor penuh data (Lihat mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA
4

Jika Anda menggunakan tabel InnoDB, Anda bisa mendapatkan ukuran untuk data / indeks individual dari mysql.innodb_index_stats. Stat 'size' berisi jawabannya, di halaman, jadi Anda harus mengalikannya dengan ukuran halaman, yaitu 16K secara default .

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

PRIMER indeks adalah data itu sendiri.

Vajk Hermecz
sumber
1
Ini mengasumsikan Anda memiliki data dalam tabel; Sepertinya OP ingin memperkirakan sebelum mengisi.
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';

dengan mengeksekusi kueri ini Anda bisa mendapatkan ukuran yang digunakan untuk Datadan Indexdari sebuah tabel, Anda dapat memeriksa ukuran ini terhadap # baris dan memperkirakan 1 juta baris

Peter Venderberghe
sumber
1
Saya tidak yakin tetapi apakah ini akan memberikan hasil yang akurat? Sudahkah Anda menguji ini?
Abdul Manaf
Sebenarnya saya sedang menguji hasil permintaan ini secara berkala untuk melihat pertumbuhan (%) ukuran wrt
Peter Venderberghe
0

Jika Anda belum memiliki data, berikut adalah beberapa kiat. Berikut ini berlaku untuk InnoDB. (MyISAM jauh lebih sederhana, dan lebih kecil.)

Jangan gunakan CHARuntuk kolom panjang variabel. Apa CHARACTER SETyang kamu gunakan Ascii membutuhkan satu byte per karakter; utf8mb4 membutuhkan antara 1 dan 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

Total = sekitar 80 byte.

Lipat gandakan 80 dengan antara 2 dan 3 untuk memperhitungkan berbagai biaya overhead. Kemungkinan besar tabel baris 1M akan berada di antara 160MB dan 240MB.

Untuk mengukur indeks tunggal, misalnya CountryCode3 byte:

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.

Catatan:

  • Hanya node daun (dari BTrees) yang perlu dihitung; overhead untuk node non-daun biasanya 1%.

  • Itu PRIMARY KEY"berkerumun" dengan data, sehingga tidak perlu untuk menghitungnya.

  • Jika Anda tidak memiliki PK eksplisit, maka Anda perlu menambahkan 6 byte ke ukuran baris untuk memungkinkan PK buatan.

  • ROW_FORMAT = COMPRESSEDmemberi Anda penyusutan 2: 1. (Ini tidak sebagus tingkat kompresi zip (dll) khas 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";adalah cara cepat untuk menghitung ukuran 'aktual'. Lihat Data_lengthuntuk data dan PK; Index_lengthuntuk indeks sekunder, dan Data_freeuntuk beberapa hal lainnya.

  • Jarang Index_lengthmelebihi Data_length. Namun itu tidak "salah" untuk itu terjadi.

Rick James
sumber
-1

Itu membosankan. Tetapi detailnya ada di dokumen .

Agar seakurat mungkin, yang jarang diperlukan, Anda harus membaca tentang struktur tabel dan struktur indeks juga.

Jika saya berada di posisi Anda, saya akan membuat tabel, mengisinya dengan sejuta baris data uji, dan mengukur perubahan ukuran. Bergantung pada aplikasi Anda, Anda mungkin perlu mempertimbangkan ukuran file log transaksi.

Mike Sherrill 'Cat Recall'
sumber