web-dev-qa-db-fra.com

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

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

Pour un exemple, nous avons un table City avec 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'index de cette table en 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.

28
Abdul Manaf

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 de code 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 prend pas en compte la gestion des BTREE ou 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 !!!

52
RolandoMySQLDBA

Si vous utilisez des tables InnoDB, vous pouvez obtenir la taille des données/index individuels à partir de mysql.innodb_index_stats. La statistique 'size' contient la réponse, en pages, vous devez donc la multiplier par la taille de la page, c'est-à-dire 16K 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.

4
Vajk Hermecz

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.)

N'utilisez pas CHAR pour les colonnes de longueur variable. Quoi CHARACTER SET Utilises-tu? 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, disons CountryCode de 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 1%.

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

  • Si vous ne disposez pas d'un PK explicite, vous devez ajouter 6 octets à la taille de ligne pour autoriser le PK fabriqué.

  • ROW_FORMAT = COMPRESSED vous donne un retrait d'environ 2: 1. (Ce n'est pas aussi bon que le 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_length pour les données et PK; Index_length pour les index secondaires et Data_free pour d'autres choses.

  • C'est rare pour Index_length à dépasser Data_length. Cependant, ce n'est pas "faux" que cela se produise.

0
Rick James
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 Data et Index d'une table, vous pouvez vérifier cette taille par rapport au nombre de lignes et prévoir 1 million de lignes

0
Peter Venderberghe