sql >> データベース >  >> RDS >> Mysql

可能なよりも長い平均行長

    • avg_row_lengthのため data_length / rowsです 。

    data_length 基本的には、ディスク上のテーブルの合計サイズです。 。 InnoDBテーブルは、単なる行のリストではありません。したがって、余分なオーバーヘッドがあります。

    • InnoDBの行はデータ以上のものであるため。

    上記と同様に、各行にはいくらかのオーバーヘッドがあります。これで、行のサイズが大きくなります。 InnoDBテーブルは、詰め込まれたデータのリストだけではありません。効率的に機能するには、少し余分な空きスペースが必要です。

    • データはブロック単位でディスクに保存され、それらのブロックは常にいっぱいになるとは限らないためです。

    ディスクは、通常4K、8K、または16Kのブロック にデータを保存します。 。物事がこれらのブロックに完全に収まらない場合があるため、空の部分を取得できます。スペース

    以下に示すように、MySQLはテーブルをブロック単位で割り当てます。そして、テーブルを大きくする必要がないようにするために必要な量よりも多くを割り当てることになります(これは遅くなり、ディスクの断片化 物事がさらに遅くなります。

    これを説明するために、空のテーブルから始めましょう。

    mysql> create table foo ( id smallint(5) unsigned NOT NULL );
    mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
    +-------------+------------+----------------+
    | data_length | table_rows | avg_row_length |
    +-------------+------------+----------------+
    |       16384 |          0 |              0 |
    +-------------+------------+----------------+
    

    何も保存しないために、16Kまたは4つの4Kブロックを使用します。空のテーブルにはこのスペースは必要ありませんが、MySQLは、大量のデータをテーブルに入れることを想定してこのスペースを割り当てました。これにより、挿入ごとにコストのかかる再割り当てを行う必要がなくなります。

    次に、行を追加しましょう。

    mysql> insert into foo (id) VALUES (1);
    mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
    +-------------+------------+----------------+
    | data_length | table_rows | avg_row_length |
    +-------------+------------+----------------+
    |       16384 |          1 |          16384 |
    +-------------+------------+----------------+
    

    テーブルはそれ以上大きくなりませんでした、それが持っているそれらの4つのブロック内のすべての未使用のスペースがあります。 16Kのavg_row_lengthを意味する1つの行があります。明らかにばかげている。別の行を追加しましょう。

    mysql> insert into foo (id) VALUES (1);
    mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
    +-------------+------------+----------------+
    | data_length | table_rows | avg_row_length |
    +-------------+------------+----------------+
    |       16384 |          2 |           8192 |
    +-------------+------------+----------------+
    

    同じこと。 16Kがテーブルに割り当てられ、そのスペースを使用して2行が割り当てられます。 1行あたり8Kというばかげた結果。

    行をどんどん挿入しても、テーブルサイズは同じままで、割り当てられたスペースをどんどん使い果たし、avg_row_length 現実に近づきます。

    mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';                                                                     
    +-------------+------------+----------------+
    | data_length | table_rows | avg_row_length |
    +-------------+------------+----------------+
    |       16384 |       2047 |              8 |
    +-------------+------------+----------------+
    

    ここでもtable_rowsが表示され始めます 不正確になります。間違いなく2048行挿入しました。

    もう少し挿入すると...

    mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
    +-------------+------------+----------------+
    | data_length | table_rows | avg_row_length |
    +-------------+------------+----------------+
    |       98304 |       2560 |             38 |
    +-------------+------------+----------------+
    

    (512行を挿入し、table_rows 何らかの理由で現実​​に戻った)

    MySQLは、テーブルにより多くのスペースが必要であると判断したため、サイズが変更され、より多くのディスクスペースを取得しました。 avg_row_length 再びジャンプしました。

    後で必要になると想定して、512行に必要なスペースよりもはるかに多くのスペースを取得しました。現在は96Kまたは244Kブロックです。これにより、実行する必要のある潜在的に遅い再割り当ての数が最小限に抑えられ、ディスクの断片化が最小限に抑えられます。

    これは、すべてのスペースが埋められたという意味ではありません 。これは、MySQLが、効率的に実行するためにより多くのスペースが必要になるほど十分にいっぱいであると考えたことを意味します。その理由を知りたい場合は、ハッシュテーブル を調べてください。 動作します。 InnoDBがハッシュテーブルを使用するかどうかはわかりませんが、原則が適用されます。一部のデータ構造は、空きスペースがある場合に最適に動作します。

    テーブルで使用されるディスクは、テーブルの行数と列のタイプに直接関係していますが、正確な式を理解するのは難しく、MySQLのバージョンごとに異なります。あなたの最善の策は、いくつかの経験的なテストを行い、正確な数を取得することは決してないだろうと自分自身を辞任することです。




    1. InnoDBに1つまたは複数のテーブルの外部キーを再チェックするように強制しますか?

    2. Amazonec2のリモートpostgresqlサーバーに接続します

    3. UNIONがPostgreSQLでどのように機能するか

    4. このphpmysqlコードを改善する方法は?