Como estimar / prever o tamanho dos dados e o tamanho do índice de uma tabela no MySQL

26

Estou descobrindo qual é a melhor maneira de estimar o tamanho de uma tabela para que estudei muitos blogs e fóruns, mas não consegui encontrar nenhuma resposta precisa

Por exemplo, temos uma tabela City with InnoDB engine , digamos que no futuro (no próximo 1 ano) ele terá 1 milhão de registros, então qual será o tamanho estimado dos dados e o tamanho do índice dessa tabela nesse período.

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)

ATUALIZAR

Qual será o limite superior estimado (tamanho máximo da tabela) com 1 milhão de registros e como podemos estimar.

Abdul Manaf
fonte
Isso é ótimo. mas é possível obter a coluna do tamanho do índice. O que significa é se você tiver uma tabela com (digamos) 5 colunas indexadas. Podemos obter o tamanho do índice de cada um deles? Vou fazer isso como outra pergunta. graças
Sushil

Respostas:

51

Dada a descrição da tabela, vejo

  • 66 bytes por linha de dados
  • 4 bytes por linha para a chave primária
  • 7 bytes por linha para o índice de código do país
    • 3 bytes para o país
    • 4 bytes para a chave em cluster anexada ao código do país
  • Total de 77 bytes de dados e chaves
  • Isso não leva em conta a limpeza para BTREEs ou fragmentação de espaço de tabela

Para um milhão de linhas, isso equivaleria a 77.000.000 bytes (73,43 MB)

Quanto à medição da tabela, para uma determinada tabela mydb.mytable, você pode executar esta consulta

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;

Para medir todas as tabelas agrupadas por banco de dados e mecanismo de armazenamento

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;

Execute essas consultas e poderá acompanhar as alterações no uso do disco do banco de dados / mecanismo.

De uma chance !!!

RolandoMySQLDBA
fonte
11
Esta é realmente uma ótima consulta para visualizar todos os tamanhos de tabela.
ghayes
Os CHARcomprimentos precisam ser multiplicados por 3, se você tiver CHARSET utf8. A sobrecarga inteira pode ser estimada duplicando ou triplicando o cálculo.
Rick James
@RolandoMySQLDBA, você sabe se é possível calcular o tamanho da linha "real" de uma tabela com o objetivo de comparar com o tamanho real (tabela compactada) e obter a proporção de compressão?
ceinmart 19/06
O @ceinmart innodb_page_size é fixo (16K ou 16384 por padrão) e se torna o limite onde as linhas e agrupadas ou divididas. Alterar innodb_page_size pode alterar o armazenamento de dados para bons ou maus. Com base no quão cheia ou esparsa é uma linha (especialmente com a presença de TEXT / BLOB / VARCHAR). Na melhor das hipóteses, você deve comparar o tamanho do arquivo .ibd com o relatório do esquema para estimar uma proporção. Você também pode precisar executar uma NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;) para obter uma proporção precisa. O esforço pode não valer a pena.
RolandoMySQLDBA 19/06
@ceinmart Lembre-se de que alterar innodb_page_size não é uma configuração tabela a tabela. Você precisaria fazer uma exportação completa dos dados (consulte mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA
4

Se você estiver usando tabelas do InnoDB, poderá obter o tamanho dos dados / índices individuais mysql.innodb_index_stats. A estatística 'size' contém a resposta, em páginas, portanto você deve multiplicá-la pelo tamanho da página, ou seja, 16K por padrão .

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

O índice PRIMARY é os próprios dados.

Vajk Hermecz
fonte
11
Isso pressupõe que você tenha dados na tabela; Parece que o OP quer estimar antes de preencher.
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';

Ao executar esta consulta, você pode obter o tamanho usado para Datae Indexde uma tabela. Você pode verificar esse tamanho em relação ao número de linhas e prever 1 milhão de linhas

Peter Venderberghe
fonte
11
Não tenho certeza, mas isso dará a alguns resultados precisos? você já testou isso?
Abdul Manaf
Na verdade, eu estou testando este resultado consulta periodicamente para ver o crescimento (%) wrt tamanho
Peter Venderberghe
0

Se você ainda não possui dados, aqui estão algumas dicas. O seguinte se aplica ao InnoDB. (MyISAM é muito mais simples e menor.)

Não use CHARpara colunas de comprimento variável. O que CHARACTER SETvocê está usando? Ascii precisa de um byte por caractere; utf8mb4 precisa entre 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

Total = cerca de 80 bytes.

Multiplique o 80 por 2 e 3 para contabilizar várias despesas gerais. Provavelmente, a tabela de 1 milhão de linhas estará entre 160 MB e 240 MB.

Para medir um único índice, por exemplo, CountryCode3 bytes:

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.

Notas:

  • Somente os nós folha (de BTrees) precisam ser calculados; a sobrecarga para os nós não-folha é tipicamente 1%.

  • O PRIMARY KEYé "agrupado" com os dados, portanto não há necessidade de calculá-los.

  • Se você não tiver uma PK explícita, precisará adicionar 6 bytes ao tamanho da linha para permitir a PK fabricada.

  • ROW_FORMAT = COMPRESSEDfornece um encolhimento 2: 1. (Isso não é tão bom quanto a taxa de compactação típica de zip (etc) de 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";é a maneira rápida de calcular o tamanho 'real'. Veja Data_lengthpara dados e PK; Index_lengthpara índices secundários e Data_freepara outras coisas.

  • É raro Index_lengthexceder Data_length. No entanto, não é "errado" que isso aconteça.

Rick James
fonte
-1

É entediante. Mas os detalhes estão nos documentos .

Para ser o mais preciso possível, o que raramente é necessário, você também precisará ler sobre a estrutura da tabela e a estrutura do índice.

Se você estivesse no seu lugar, criaria a tabela, preencheria-a com um milhão de linhas de dados de teste e mediria a alteração no tamanho. Dependendo do seu aplicativo, talvez seja necessário levar em consideração o tamanho dos arquivos de log de transações.

Mike Sherrill 'Recorde Gato'
fonte