2列のテーブルがあります。両方の列のタイプはvarchar(38)
に設定されます。列の1つに空の値を含む行を作成すると、値が空でなかった場合と同じ記憶域が使用されますか?
言い換えると、MySQLは、行が作成されたときに、列のストレージスペースを(そのタイプに応じて)予約しますか?
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
値が列のストレージに占めるものです
ここで、最初のポイントがもたらしたもののため、CHARとVARCHARのどちらを使用するかを決定する必要があります。
NULL値の固定スペースを予約すると、インデックスページの断片化を引き起こすことなく、列をNULLから非NULL値に更新できます。
これにより、NULL以外のデータが格納されると、行の断片化が発生するのを防ぎます。これは、MyISAMに関して前に説明したものです。以前の投稿を参照してください 固定サイズのフィールドでCHARとVARCHARを使用すると、パフォーマンスにどのような影響がありますか? 。
Varchar列に定義する長さに関係なく、空の列が使用するストレージスペースは同じになります。
これは、varchar列によって使用されるスペースのみを扱い、行、そのインデックス、主キー、およびその他の列によって使用されるストレージ領域の合計は考慮しません。
Ypercubeが彼のコメントで言及しているように、少なくとも1つのnull許容列が存在する場合、行ストレージ全体として追加の考慮事項があります。
レコードヘッダーの可変長部分には、NULL列を示すビットベクトルが含まれています。 NULLの可能性がある9〜15列のいずれかがある場合、ビットベクトルは2バイトを使用します。
...
ヘッダーの可変長部分には、可変長列の長さも含まれます。各長さは、列の最大長に応じて、1バイトまたは2バイトになります。インデックス内のすべての列がNOT NULLで固定長の場合、レコードヘッダーには可変長部分がありません
そして、はい、使用するストレージスペースは、選択したタイプ(固定または可変)、照合、およびエンジンなどの他の要素に基づいて変化します。
MySQLはここでデータストレージの最適化に関する推奨事項を作成します: データサイズの最適化
更新
Varcharに関するもう1つの考慮事項とそれがメモリです。 MySQLでは、可変長カラムのサイズをできるだけ制限することが重要です。列が可変であり、使用されるストレージスペースが可変であっても、MySQLは値を格納するために固定チャンクでメモリを割り当てます。たとえば、varchar(200)はvarchar(5)よりも多くのメモリを使用します。これはストレージスペースの問題ではありませんが、列を定義するときに考慮する必要があります。