Come stimare / prevedere la dimensione dei dati e la dimensione dell'indice di una tabella in MySQL


26

Sto trovando qual è il modo migliore per stimare le dimensioni di una tabella per cui ho studiato molti blog e forum ma non sono riuscito a trovare una risposta precisa

Per un esempio abbiamo una tabella City con motore InnoDB , diciamo in futuro (nel prossimo anno) che avrà 1 milione di record, quindi quali saranno le dimensioni dei dati stimati e le dimensioni dell'indice di quella tabella in questo periodo.

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)

AGGIORNARE

Quale sarà il limite superiore stimato (dimensione massima della tabella) con 1 milione di record e come possiamo stimarlo.


Questo è fantastico ma è possibile ottenere la colonna della dimensione dell'indice saggia. Ciò che è medio è se hai una tabella con (diciamo) 5 colonne indicizzate. Possiamo ottenere la dimensione dell'indice di ciascuno di essi? Lo farò come un'altra domanda. grazie
Sushil,

Risposte:


51

Vista la descrizione della tabella, vedo

  • 66 byte per riga di dati
  • 4 byte per riga per la chiave primaria
  • 7 byte per riga per l'indice del codice paese
    • 3 byte per il paese
    • 4 byte per chiave cluster allegata al prefisso internazionale
  • Totale di 77 byte di dati e chiavi
  • Ciò non tiene conto delle pulizie per BTREEs o frammentazione del tablespace

Per un milione di righe, sarebbe 77.000.000 di byte (73,43 MB)

Per quanto riguarda la misurazione della tabella, per una determinata tabella mydb.mytable, è possibile eseguire questa query

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;

Per misurare tutte le tabelle raggruppate per Database e 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;

Esegui queste query e puoi tenere traccia delle modifiche nell'utilizzo del disco del database / motore.

Provaci !!!


1
Questa è una query davvero eccezionale per visualizzare tutte le dimensioni della tabella.
ghayes,

Le CHARlunghezze devono essere moltiplicate per 3 se lo hai CHARSET utf8. L'intero sovraccarico può essere stimato raddoppiando o triplicando il calcolo.
Rick James,

@RolandoMySQLDBA, sai se è possibile calcolare la dimensione della riga "reale" di una tabella con l'obiettivo di confrontarla con la dimensione reale (tabella compressa) e ottenere il rapporto di compressione?
Ceinmart,

@ceinmart innodb_page_size è fisso (16K o 16384 di default) e diventa il confine in cui le righe e raggruppate o divise. La modifica di innodb_page_size può alterare l'archiviazione dei dati nel bene e nel male. In base alla quantità o alla sparizione di una riga (specialmente con la presenza di TEXT / BLOB / VARCHAR). Nella migliore delle ipotesi, è necessario confrontare la dimensione del file .ibd con ciò che lo schema riporta per stimare un rapporto. Potrebbe anche essere necessario eseguire una TABELLA ALTER NULL ( ALTER TABLE ... ENGINE=InnoDB;) per ottenere un rapporto accurato. Lo sforzo potrebbe non valerne la pena.
RolandoMySQLDBA

@ceinmart Ricorda che cambiare cappello innodb_page_size non è un'impostazione tabella per tabella. Dovresti fare un'esportazione completa dei dati (vedi mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA

4

Se si utilizzano tabelle InnoDB, è possibile ottenere la dimensione per i dati / i singoli indici da mysql.innodb_index_stats. La statistica 'size' contiene la risposta, in pagine, quindi devi moltiplicarla per la dimensione della pagina, che è 16K per impostazione predefinita .

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

L'indice PRIMARY è i dati stessi.


1
Questo presuppone che tu abbia dei dati nella tabella; sembra che l'OP voglia stimare prima di popolare.
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';

eseguendo questa query è possibile ottenere la dimensione utilizzata per Datae Indexdi una tabella, è possibile verificare questa dimensione rispetto al numero di righe e prevedere 1 milione di righe


1
Non sono sicuro, ma questo darà alcuni risultati precisi? l'hai mai provato?
Abdul Manaf,

In realtà sto testando periodicamente questo risultato della query per vedere la crescita (%) delle dimensioni del
wrt

0

Se non disponi ancora di dati, ecco alcuni suggerimenti. Quanto segue si applica a InnoDB. (MyISAM è molto più semplice e più piccolo.)

Non utilizzare CHARper colonne di lunghezza variabile. Che cosa CHARACTER SETstai usando? Ascii ha bisogno di un byte per carattere; utf8mb4 necessita tra 1 e 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

Totale = circa 80 byte.

Moltiplica gli 80 per 2 e 3 per tenere conto delle varie spese generali. Molto probabilmente la tabella delle righe 1M sarà compresa tra 160 MB e 240 MB.

Per misurare un singolo indice, per esempio CountryCodedi 3 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.

Gli appunti:

  • Solo i nodi foglia (di BTrees) devono essere calcolati; l'overhead per i nodi non foglia è in genere dell'1%.

  • Il PRIMARY KEYè "raggruppati" con i dati, quindi non c'è bisogno di calcolarlo.

  • Se non si dispone di un PK esplicito, è necessario aggiungere 6 byte alla dimensione della riga per consentire il PK fabbricato.

  • ROW_FORMAT = COMPRESSEDti dà un restringimento di 2: 1. (Questo non è buono come il tipico tasso di compressione zip (ecc.) Di 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";è il modo rapido per calcolare la dimensione "reale". Vedere Data_lengthper dati e PK; Index_lengthper gli indici secondari e Data_freeper alcune altre cose.

  • È raro Index_lengthsuperare Data_length. Tuttavia non è "sbagliato" che ciò accada.


-1

È noioso. Ma i dettagli sono nei documenti .

Per essere il più precisi possibile, cosa che raramente è necessaria, dovrai leggere anche la struttura della tabella e dell'indice.

Se fossi nei tuoi panni, costruirei la tabella, la popolerei con un milione di righe di dati di test e misurerei la modifica delle dimensioni. A seconda dell'applicazione, potrebbe essere necessario prendere in considerazione anche la dimensione dei file di registro delle transazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.