Comment estimer / prédire la taille des données et la taille de l'index d'une table dans MySQL

26

Je trouve quelle est la meilleure façon d'estimer la taille d'un tableau pour cela j'ai étudié beaucoup de blogs et de forums mais je n'ai pas trouvé de réponse précise

Par exemple, nous avons un tableau City avec le moteur InnoDB , disons à l'avenir (au cours de la prochaine année), il y aura 1 million d'enregistrements, alors quelle sera la taille estimée des données et la taille de l'indice de ce tableau pendant cette période.

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)

MISE À JOUR

Quelle sera la limite supérieure estimée (taille maximale du tableau) avec 1 million d'enregistrements et comment pouvons-nous l'estimer.

Abdul Manaf
la source
C'est bien. mais est-il possible d'obtenir la colonne de taille d'index sage. Cela signifie que si vous avez un tableau avec (disons) 5 colonnes indexées. Pouvons-nous obtenir la taille d'index de chacun d'eux? Je vais poser cette question comme une autre question. merci
Sushil

Réponses:

51

Compte tenu de la description du tableau, je vois

  • 66 octets par ligne de données
  • 4 octets par ligne pour la clé primaire
  • 7 octets par ligne pour l'index des codes de pays
    • 3 octets pour le pays
    • 4 octets pour la clé en cluster attachée au code du pays
  • Total de 77 octets de données et de clés
  • Cela ne tient pas compte de la gestion interne des BTREE ou de la fragmentation de l'espace disque logique

Pour un million de lignes, cela représenterait 77 000 000 octets (73,43 Mo)

Quant à la mesure de la table, pour une table donnée mydb.mytable, vous pouvez exécuter cette requête

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;

Pour mesurer toutes les tables regroupées par base de données et moteur de stockage

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;

Exécutez ces requêtes et vous pouvez suivre les modifications de l'utilisation du disque de la base de données / du moteur.

Essaie !!!

RolandoMySQLDBA
la source
1
Il s'agit d'une très bonne requête pour afficher toutes les tailles de votre table.
ghayes
Les CHARlongueurs doivent être multipliées par 3 si vous en avez CHARSET utf8. L'ensemble des frais généraux peut être estimé en doublant ou en triplant le calcul.
Rick James
@RolandoMySQLDBA, savez-vous s'il est possible de calculer la taille de ligne "réelle" d'une table avec l'objectif de comparer avec la taille réelle (table compressée) et d'obtenir le rapport de compression?
ceinmart
@ceinmart innodb_page_size est fixe (16K ou 16384 par défaut) et devient la frontière où les lignes et groupées ou divisées. La modification de innodb_page_size peut modifier le stockage des données pour le meilleur ou pour le pire, en fonction du niveau de remplissage ou de la rareté d'une ligne (en particulier avec la présence de TEXT / BLOB / VARCHAR). Au mieux, vous devez comparer la taille du fichier .ibd à celle du rapport de schéma pour estimer un ratio. Vous devrez peut-être également effectuer une NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;) pour obtenir un rapport précis. L'effort n'en vaut peut-être pas la peine.
RolandoMySQLDBA
@ceinmart Gardez à l'esprit que le changement de chapeau innodb_page_size n'est pas un paramètre table par table. Vous auriez besoin de faire une exportation complète des données (Voir mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA
4

Si vous utilisez des tables InnoDB, vous pouvez obtenir la taille des données / index individuels à partir de mysql.innodb_index_stats. La statistique «taille» contient la réponse, en pages, vous devez donc la multiplier par la taille de la page, qui est 16 Ko par défaut .

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

L'index PRIMARY est les données elles-mêmes.

Vajk Hermecz
la source
1
Cela suppose que vous avez des données dans le tableau; semble que le PO souhaite estimer avant de remplir.
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';

en exécutant cette requête, vous pouvez obtenir la taille utilisée pour Dataet Indexd'une table, vous pouvez vérifier cette taille par rapport au nombre de lignes et prévoir 1 million de lignes

Peter Venderberghe
la source
1
Je ne suis pas sûr, mais cela donnera-t-il des résultats précis? avez-vous déjà testé cela?
Abdul Manaf
En fait, je teste régulièrement le résultat de cette requête pour voir la croissance (%) par rapport à la taille
Peter Venderberghe
0

Si vous ne disposez pas encore de données, voici quelques conseils. Ce qui suit s'applique à InnoDB. (MyISAM est beaucoup plus simple et plus petit.)

Ne pas utiliser CHARpour les colonnes de longueur variable. Qu'utilisez CHARACTER SET-vous? Ascii a besoin d'un octet par caractère; utf8mb4 a besoin de 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

Total = environ 80 octets.

Multipliez le 80 par entre 2 et 3 pour tenir compte des différents frais généraux. La table de lignes 1 Mo sera probablement comprise entre 160 Mo et 240 Mo.

Pour mesurer un seul index, par exemple CountryCodede 3 octets:

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.

Remarques:

  • Seuls les nœuds feuilles (de BTrees) doivent être calculés; la surcharge pour les nœuds non-feuilles est généralement de 1%.

  • Le PRIMARY KEYest "regroupé" avec les données, il n'est donc pas nécessaire de le calculer.

  • Si vous n'avez pas de PK explicite, vous devez ajouter 6 octets à la taille de ligne pour autoriser le PK fabriqué.

  • ROW_FORMAT = COMPRESSEDvous donne un rétrécissement de 2: 1. (Ce n'est pas aussi bon qu'un taux de compression zip (etc.) typique de 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";est le moyen rapide de calculer la taille «réelle». Voir Data_lengthpour les données et PK; Index_lengthpour les index secondaires et Data_freepour d'autres éléments.

  • Il est rare Index_lengthde dépasser Data_length. Cependant, ce n'est pas "faux" que cela se produise.

Rick James
la source
-1

C'est fastidieux. Mais les détails sont dans les documents .

Pour être aussi précis que possible, ce qui est rarement nécessaire, vous devrez également lire la structure de la table et la structure de l'index.

Si j'étais à votre place, je construirais le tableau, le remplirais avec un million de lignes de données de test et mesurerais le changement de taille. Selon votre application, vous devrez peut-être également prendre en compte la taille des fichiers journaux des transactions.

Mike Sherrill 'Cat Recall'
la source