MySQLのテーブルのデータサイズとインデックスサイズを推定/予測する方法


26

私が発見していますテーブルの大きさを推定するための最良の方法は何か私はブログやフォーラムの多くを学んだが、任意の正確な答えを見つけることができていることのために

たとえば、InnoDBエンジンを搭載しテーブルCityがあり、将来(今後1年)に100万件のレコードがあるため、この期間のそのテーブルの推定データサイズとインデックスサイズはどうなるでしょう。

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)

更新

100万レコードの推定上限(テーブルの最大サイズ)とは何ですか?


これは素晴らしい。しかし、インデックスサイズを列単位で取得することは可能ですか。つまり、5つの列にインデックスが付けられたテーブルがある場合です。それぞれのインデックスサイズを取得できますか?これを別の質問として尋ねます。ありがとう
スシル

回答:


51

テーブルの説明を考えると、私は見る

  • データの行ごとに66バイト
  • 主キーの行ごとに4バイト
  • 国コード索引の行ごとに7バイト
    • 国の3バイト
    • 国コードに添付されたクラスター化キーの場合は4バイト
  • 合計77バイトのデータとキー
  • これは、BTREEまたはテーブルスペースフラグメンテーションのハウスキーピングを考慮しません。

100万行の場合、77,000,000バイト(73.43 MB)

テーブルの測定に関しては、特定のテーブルmydb.mytableに対して、このクエリを実行できます

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;

データベースとストレージエンジンごとにグループ化されたすべてのテーブルを測定するには

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;

これらのクエリを実行すると、データベース/エンジンのディスク使用量の変化を追跡できます。

試してみる !!!


1
これは、すべてのテーブルサイズを表示するための非常に優れたクエリです。
ghayes

CHARあなたが持っている場合は長さが3で乗算する必要がありますCHARSET utf8。計算を2倍または3倍にすることで、オーバーヘッド全体を推定できます。
リックジェームズ

@RolandoMySQLDBA、実際のサイズ(圧縮されたテーブル)と比較し、圧縮率を取得する目的でテーブルの「実際の」行サイズを計算できるかどうかを知っていますか?
ceinmart

@ceinmart innodb_page_sizeは固定(デフォルトでは16Kまたは16384)で、行とグループ化または分割される境界になります。innodb_page_sizeを変更すると、データのストレージが良いか悪いかを変更できます。行がどの程度満たされているか、まばらであるかに基づいて(特にTEXT / BLOB / VARCHARが存在する場合)。せいぜい、.ibdファイルのサイズをスキーマレポートと比較して、比率を推定する必要があります。またALTER TABLE ... ENGINE=InnoDB;、正確な比率を取得するには、NULL ALTER TABLE()を実行する必要があります。努力する価値はないかもしれません。
RolandoMySQLDBA

@ceinmart innodb_page_sizeの変更はテーブルごとの設定ではないことに注意してください。データを完全にエクスポートする必要があります(mariadb.com/kb/en/library/how-to-change-innodb_page_sizeを参照)
RolandoMySQLDBA

4

InnoDBテーブルを使用している場合、データ/個別インデックスのサイズをから取得できますmysql.innodb_index_stats。'size'の統計情報にはページ単位の回答が含まれているため、ページサイズ(デフォルトでは16K)を掛ける必要があります

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

インデックスPRIMARYはデータそのものです。


1
これは、テーブルにデータがあることを前提としています。OPはデータを入力する前に推定したいようです。
リックジェームズ

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';

このクエリを実行するDataIndex、テーブルに使用されるサイズを取得できます。このサイズを行数に対して確認し、100万行を予測できます


1
よくわかりませんが、これにより正確な結果が得られますか?これをテストしたことがありますか?
アブドゥルマナフ

実際に私はサイズWRT成長(%)を参照するために、定期的にこのクエリの結果をテストしてい
ピーターVenderberghe

0

データがまだない場合は、ここにいくつかのヒントがあります。以下はInnoDBに適用されます。(MyISAMは、はるかに単純で小さくなっています。)

CHAR可変長列には使用しないでください。何CHARACTER SETを使っていますか?Asciiには文字ごとに1バイトが必要です。utf8mb4には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

合計=約80バイト。

80に2〜3を掛けて、さまざまなオーバーヘッドを考慮します。ほとんどの場合、1M行テーブルは160MBから240MBの間です。

たとえばCountryCode3バイトの単一のインデックスを測定するには:

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.

ノート:

  • (BTreeの)リーフノードのみを計算する必要があります。非リーフノードのオーバーヘッドは通常 1%です。

  • PRIMARY KEYデータと、それを計算する必要はありません「クラスタ化」されます。

  • 明示的なPKがない場合、製造されたPKを許可するために、行サイズに6バイトを追加する必要があります。

  • ROW_FORMAT = COMPRESSED約2:1の収縮が得られます。(これは、3:1の一般的なzip(など)圧縮率ほど良くありません。)

  • SHOW TABLE STATUS LIKE "tablename";「実際の」サイズを計算する簡単な方法です。Data_lengthデータとPKを参照してください。Index_lengthセカンダリインデックス、およびData_free他のいくつかのもの。

  • Index_lengthを超えることはまれですData_length。しかし、それが起こるのは「間違った」ことではありません。


-1

面倒です。しかし、詳細はドキュメントにあります。

めったに必要ではないができるだけ正確にするために、テーブル構造とインデックス構造についても読む必要があります。

私があなたの靴を履いているなら、テーブルを作成し、100万行のテストデータをそこに入れて、サイズの変化を測定します。アプリケーションによっては、トランザクションログファイルのサイズも考慮する必要がある場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.