web-dev-qa-db-ja.com

空の列値は、入力された列値と同じ記憶域を占有しますか?

2列のテーブルがあります。両方の列のタイプはvarchar(38)に設定されます。列の1つに空の値を含む行を作成すると、値が空でなかった場合と同じ記憶域が使用されますか?

言い換えると、MySQLは、行が作成されたときに、列のストレージスペースを(そのタイプに応じて)予約しますか?

17
Haris ur Rehman

Innodb物理行構造、REDUNDANT ROW_FORMATの下の箇条書き#7 から

SQL NULL値は、レコードディレクトリに1バイトまたは2バイトを予約します。さらに、SQL NULL値は、可変長列に格納されている場合、レコードのデータ部分にゼロバイトを予約します固定長の列では、レコードのデータ部分の列の固定長を予約します。NULL値用の固定スペースを予約することにより、インデックスページの断片化を引き起こすことなく、列をNULLから非NULL値に更新できます。

Innodb物理行構造、COMPACT ROW_FORMATの下の箇条書き#2 から

レコードヘッダーの可変長部分には、NULL列を示すビットベクトルが含まれています。 NULLの可能性があるインデックスの列数がNの場合、ビットベクトルはCEILING(N/8)バイトを占有します。 (たとえば、NULLの可能性がある9〜15の列がある場合、ビットベクトルは2バイトを使用します。)NULLの列はスペースを占有しませんこのベクトルのビット以外。ヘッダーの可変長部分には、可変長列の長さも含まれます。各長さは、列の最大長に応じて、1バイトまたは2バイトになります。インデックス内のすべての列がNOT NULLであり、固定長である場合、レコードヘッダーには可変長部分がありません。

これらの箇条書きに基づいて、以下はNULL値が列のストレージに占めるものです

  • 可変長:NULL値は行自体にストレージを使用しません
  • 固定長:予約スペースを使用します

ここで、最初のポイントがもたらしたもののため、CHARとVARCHARのどちらを使用するかを決定する必要があります。

NULL値の固定スペースを予約すると、インデックスページの断片化を引き起こすことなく、列をNULLから非NULL値に更新できます。

これにより、NULL以外のデータが格納されると、行の断片化が発生するのを防ぎます。これは、MyISAMに関して前に説明したものです。以前の投稿を参照してください 固定サイズのフィールドでCHARとVARCHARを使用すると、パフォーマンスにどのような影響がありますか?

12
RolandoMySQLDBA

Varchar列に定義する長さに関係なく、空の列が使用するストレージスペースは同じになります。

CHARおよびVARCHARタイプ

enter image description here

これは、varchar列によって使用されるスペースのみを扱い、行、そのインデックス、主キー、およびその他の列によって使用されるストレージ領域の合計は考慮しません。

Ypercubeが彼のコメントで言及しているように、少なくとも1つのnull許容列が存在する場合、行ストレージ全体として追加の考慮事項があります。

Innodb物理行構造

レコードヘッダーの可変長部分には、NULL列を示すビットベクトルが含まれています。 NULLの可能性がある9〜15列のいずれかがある場合、ビットベクトルは2バイトを使用します。

...

ヘッダーの可変長部分には、可変長列の長さも含まれます。各長さは、列の最大長に応じて、1バイトまたは2バイトになります。インデックス内のすべての列がNOT NULLで固定長の場合、レコードヘッダーには可変長部分がありません

そして、はい、使用するストレージスペースは、選択したタイプ(固定または可変)、照合、およびエンジンなどの他の要素に基づいて変化します。

MySQLはここでデータストレージの最適化に関する推奨事項を作成します: データサイズの最適化

更新

Varcharに関するもう1つの考慮事項とそれがメモリです。 MySQLでは、可変長カラムのサイズをできるだけ制限することが重要です。列が可変であり、使用されるストレージスペースが可変であっても、MySQLは値を格納するために固定チャンクでメモリを割り当てます。たとえば、varchar(200)はvarchar(5)よりも多くのメモリを使用します。これはストレージスペースの問題ではありませんが、列を定義するときに考慮する必要があります。

8
Craig Efrein