質問
MySQLでは、nullはパフォーマンスとストレージ(スペース)をどのように賢くしますか?
例:
TINYINT:1バイト NULL 1バイトのTINYINT +何とかNULLを格納しますか?
解決
使用するストレージエンジンによって異なります。
MyISAM形式では、各行ヘッダーには、NULL状態をエンコードするために各列に1ビットのビットフィールドが含まれています。 NULLの列は依然としてスペースを占有するため、NULLがストレージを削減することはありません。 https://dev.mysql.com/doc/internals/en/をご覧ください。 myisam-introduction.html
InnoDBでは、各列には「フィールド開始オフセット」があります。行ヘッダー(列ごとに1または2バイト)。列がNULLの場合、そのフィールド開始オフセットの上位ビットはオンです。その場合、列をまったく保存する必要はありません。したがって、NULLがたくさんある場合、ストレージを大幅に削減する必要があります。 https://dev.mysql.com/doc/internals/をご覧ください。 ja / innodb-field-contents.html
編集:
NULLビットは行ヘッダーの一部であり、追加することは選択しません。
NULLがパフォーマンスを改善すると想像できる唯一の方法は、InnoDBでは、行にNULLが含まれている場合、データのページがより多くの行に適合する可能性があることです。したがって、InnoDBバッファーの方が効果的です。
しかし、これが実際にパフォーマンス上の大きな利点を提供する場合、私は非常に驚くでしょう。 NULLがパフォーマンスに与える影響を心配することは、マイクロ最適化の領域です。あなたは、他の場所に、お金に大きな価値を与えるエリアに注意を向けるべきです。たとえば、適切に選択されたインデックスを追加したり、データベースキャッシュの割り当てを増やしたりします。
他のヒント
Billの答えは良いですが、少し時代遅れです。 NULLを格納するための1バイトまたは2バイトの使用は、InnoDB REDUNDANT行形式にのみを適用します。 MySQL 5.0.3 InnoDBは COMPACT 行形式を使用するため、1ビットのみを使用してNULLを格納するため(もちろん1バイトが最小です)、したがって:
NULLに必要なスペース= CEILING(N / 8)バイトここで、Nは行内のNULL列の数です。
- 0 NULLS = 0バイト
- 1-8 NULL = 1バイト
- 9-16 NULLS = 2バイト
- 17-24 NULLS = 3バイト
- etc ...
COMPACT vs REDUNDANTに関するMySQLの公式サイトによると:
コンパクトな行形式では、一部の操作でCPUの使用が増加しますが、行の記憶領域が約20%減少します。ワークロードがキャッシュヒット率とディスク速度によって制限される一般的なワークロードである場合、コンパクトフォーマットの方が高速になる可能性があります。
空の文字列またはゼロでNULLを使用する利点:
- 1 NULLには1バイトが必要です
- 1つの空の文字列には1バイトが必要です(VARCHARと仮定)
- 1ゼロには4バイトが必要です(INTと仮定)
ここで貯蓄が表示され始めます:
- 8個のNULLには1バイトが必要です
- 8つの空の文字列には8バイトが必要です
- 8個のゼロには32バイトが必要です
一方で、空の文字列またはゼロにはNULLを使用することをお勧めします。これらは、より整理され、移植性があり、必要なスペースが少ないためです。パフォーマンスを改善し、スペースを節約するには、奇妙なトリックの代わりに適切なデータ型、インデックス、クエリを使用することに集中してください。
詳細: https://dev.mysql.com/doc/refman /5.7/en/innodb-physical-record.html
これらのMySQLのヒント。番号11は、これに具体的に対処しています。
まず、空の文字列値とNULL値(INTフィールドの場合:0とNULL)に違いがあるかどうかを自問します。両方を持つ理由がない場合は、NULLフィールドは必要ありません。 (OracleはNULLと空の文字列を同じものとみなすことをご存知ですか?)
NULL列には追加のスペースが必要であり、比較ステートメントが複雑になる可能性があります。できる限り避けてください。ただし、NULL値を使用する非常に具体的な理由がある人もいることを理解しています。これは必ずしも悪いことではありません。
一方で、多くの行を持たないテーブルでは、まだNULLを使用しています。これは、主にNOT NULLと言うロジックが好きだからです。
更新 後でこれを再考して、私は個人的にデータベースでNULLの代わりに0を使用したくないことを付け加えます。注意を怠ると、アプリケーションで多くの誤検知が発生する可能性があります。
dev.mysql.com/doc/refman/ 5.0 / en / is-null-optimization.html
MySQLは、col_name = constant_valueに使用できるのと同じ最適化をcol_name IS NULLで実行できます。たとえば、MySQLはインデックスと範囲を使用してIS NULLでNULLを検索できます