Schätzen / Vorhersagen der Datengröße und der Indexgröße einer Tabelle in MySQL

26

Ich finde , was der beste Weg ist, um die Größe einer Tabelle zu schätzen, für die ich viele Blogs und Foren studiert habe, aber keine genaue Antwort finden kann

Als Beispiel haben wir eine Tabelle City mit InnoDB-Engine . Nehmen wir an, dass in Zukunft (in einem Jahr) eine Million Datensätze vorhanden sein werden. Wie hoch ist also die geschätzte Daten- und Indexgröße dieser Tabelle in diesem Zeitraum?

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)

AKTUALISIEREN

Wie hoch wird die geschätzte Obergrenze (maximale Größe der Tabelle) mit 1 Million Datensätzen sein und wie können wir sie schätzen?

Abdul Manaf
quelle
Das ist toll. Es ist jedoch möglich, die Indexgröße spaltenweise zu ermitteln. Was ist gemeint, wenn Sie eine Tabelle mit (sagen wir) 5 Spalten indiziert haben. Können wir die Indexgröße jedes einzelnen von ihnen ermitteln? Ich werde dies als eine andere Frage stellen. danke
Sushil

Antworten:

51

Angesichts der Tabellenbeschreibung verstehe ich

  • 66 Bytes pro Datenzeile
  • 4 Bytes pro Zeile für den Primärschlüssel
  • 7 Bytes pro Zeile für Ländercodeindex
    • 3 Bytes für das Land
    • 4 Byte für den Clustered Key, der an den Ländercode angehängt ist
  • Insgesamt 77 Byte Daten und Schlüssel
  • Hierbei wird das Housekeeping für BTREEs oder Tablespace-Fragmentierung nicht berücksichtigt

Bei einer Million Zeilen wären das 77.000.000 Bytes (73,43 MB).

Zum Messen der Tabelle können Sie für eine gegebene Tabelle mydb.mytable diese Abfrage ausführen

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;

Zum Messen aller nach Datenbank und Speicher-Engine gruppierten Tabellen

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;

Wenn Sie diese Abfragen ausführen, können Sie Änderungen in der Datenbank- / Engine-Datenträgerverwendung nachverfolgen.

Versuche es !!!

RolandoMySQLDBA
quelle
1
Dies ist eine großartige Abfrage zum Anzeigen aller Tabellengrößen.
Ghayes
Die CHARLängen müssen mit 3 multipliziert werden, wenn Sie haben CHARSET utf8. Der gesamte Aufwand kann geschätzt werden, indem die Berechnung verdoppelt oder verdreifacht wird.
Rick James
@RolandoMySQLDBA, wissen Sie, ob es möglich ist, die "echte" Zeilengröße einer Tabelle zu berechnen, um sie mit der tatsächlichen Größe (komprimierte Tabelle) zu vergleichen und das Kompressionsverhältnis zu erhalten?
Ceinmart
@ceinmart innodb_page_size ist fest (standardmäßig 16K oder 16384) und wird zur Grenze, an der Zeilen gruppiert oder geteilt werden. Das Ändern von innodb_page_size kann die Speicherung von Daten für gut oder schlecht ändern. Dies hängt davon ab, wie gefüllt oder dünn eine Zeile ist (insbesondere bei Vorhandensein von TEXT / BLOB / VARCHAR). Im besten Fall sollten Sie die Größe der .ibd-Datei mit dem im Schemabericht angegebenen Wert vergleichen, um ein Verhältnis zu ermitteln. Möglicherweise müssen Sie auch NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;) ausführen , um ein genaues Verhältnis zu erhalten. Anstrengung kann es nicht wert sein.
RolandoMySQLDBA
@ceinmart Denken Sie daran, dass das Ändern von innodb_page_size keine tabellenweise Einstellung ist. Sie müssten die Daten vollständig exportieren (siehe mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA
4

Wenn Sie InnoDB-Tabellen verwenden, können Sie die Größe für Daten / einzelne Indizes von abrufen mysql.innodb_index_stats. Die Größenangabe enthält die Antwort in Seiten. Sie müssen sie daher mit der Seitengröße multiplizieren, die standardmäßig 16 KB beträgt .

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

Der Index PRIMARY sind die Daten selbst.

Vajk Hermecz
quelle
1
Dies setzt voraus, dass Sie Daten in der Tabelle haben. Es scheint, als ob das OP vor dem Bevölkern abschätzen möchte.
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';

Durch Ausführen dieser Abfrage können Sie die Größe für Dataund Indexeiner Tabelle ermitteln. Sie können diese Größe anhand der Anzahl der Zeilen überprüfen und für 1 Million Zeilen vorhersagen

Peter Venderberghe
quelle
1
Ich bin nicht sicher, aber wird dies einige was genaue Ergebnisse geben? Hast du das jemals getestet?
Abdul Manaf
Tatsächlich teste ich dieses Abfrageergebnis regelmäßig, um ein Wachstum (%) in Bezug auf die Größe festzustellen
Peter Venderberghe
0

Wenn Sie noch keine Daten haben, finden Sie hier einige Tipps. Für InnoDB gilt Folgendes. (MyISAM ist viel einfacher und kleiner.)

Nicht CHARfür Spalten mit variabler Länge verwenden. Was benutzt CHARACTER SETdu? ASCII benötigt ein Byte pro Zeichen; utf8mb4 benötigt zwischen 1 und 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

Gesamt = ungefähr 80 Bytes.

Multiplizieren Sie die 80 mit 2 bis 3, um verschiedene Gemeinkosten zu berücksichtigen. Höchstwahrscheinlich liegt die 1-MB-Zeilentabelle zwischen 160 MB und 240 MB.

So messen Sie einen einzelnen Index CountryCodevon beispielsweise 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.

Anmerkungen:

  • Es müssen nur die Blattknoten (von BTrees) berechnet werden. Der Overhead für die Nicht-Blatt-Knoten beträgt in der Regel 1%.

  • Die PRIMARY KEYDaten werden mit den Daten "geclustert", sodass sie nicht berechnet werden müssen.

  • Wenn Sie keine explizite PK haben, müssen Sie der Zeilengröße 6 Byte hinzufügen, um die hergestellte PK zu berücksichtigen.

  • ROW_FORMAT = COMPRESSEDergibt eine Schrumpfung von ca. 2: 1. (Dies ist nicht so gut wie die typische Komprimierungsrate für Reißverschlüsse (usw.) von 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";ist der schnelle Weg, um die 'tatsächliche' Größe zu berechnen. Siehe Data_lengthfür Daten und PK; Index_lengthfür sekundäre Indizes und Data_freefür einige andere Sachen.

  • Es ist selten Index_lengthzu übertreffen Data_length. Es ist jedoch nicht "falsch", dass dies geschieht.

Rick James
quelle
-1

Es ist langweilig. Aber die Details sind in den Dokumenten .

Um so genau wie möglich zu sein, was selten notwendig ist, müssen Sie auch die Tabellenstruktur und die Indexstruktur lesen.

Wenn ich in Ihren Schuhen stecke, würde ich die Tabelle erstellen, sie mit einer Million Zeilen Testdaten füllen und die Größenänderung messen. Abhängig von Ihrer Anwendung müssen Sie möglicherweise auch die Größe der Transaktionsprotokolldateien berücksichtigen.

Mike Sherrill 'Cat Recall'
quelle