MySQL フィールドで NOT NULL を使用する必要があるのはなぜですか?

MySQL フィールドで NOT NULL を使用する必要があるのはなぜですか?

私は最近新しい会社に入社したのですが、データベース設計にいくつか小さな問題があることに気付きました。多くのデータベース フィールドに NOT NULL がありません。これは強迫性障害末期の患者にとってはまったく耐えられないことなので、この記事を書きました。

現在の開発状況のほとんどに基づいて、すべてのフィールドをNOT NULLに設定し、デフォルト値を指定します。

  • 通常、デフォルト値は次のように設定されます。
  • 整数。通常はデフォルト値として 0 を使用します。
  • 文字列、デフォルトは空の文字列

時間はデフォルトの1970-01-01 08:00:01またはデフォルトの0000-00-00 00:00:00にすることができますが、接続パラメータにzeroDateTimeBehavior=convertToNull追加する必要があります。このデフォルトの時間形式は使用しないことをお勧めします。

しかし、理由を考えてみましょう。なぜ NOT NULL に設定する必要があるのでしょうか?

High Performance MySQL からの一節があります:

NULLを避けるようにしてください

多くのテーブルには、アプリケーションが NULL 値を格納する必要がない場合でも、NULL が列のデフォルト プロパティであるため、NULL (空の値) になる可能性がある列が含まれています。通常、NULL 値を格納する必要がある場合を除き、列が NOT NULL であることを指定するのが最適です。

NULL 列を含むクエリは、NULL 列によってインデックス、インデックス統計、および値の比較がより複雑になるため、MySQL では最適化がより困難になります。 NULL になる可能性のある列は、より多くのストレージスペースを使用するため、MySQL で特別な処理が必要になります。 NULL 対応の列にインデックスを作成すると、インデックス レコードごとに 1 バイト余分に必要になります。これにより、MyISAM では固定サイズのインデックス (単一の整数列のインデックスなど) が可変サイズのインデックスになることもあります。

一般に、NULL 可能列を NOT NULL に変更してもパフォーマンスの向上はわずかであるため、これが問題を引き起こすことが確実でない限り、まず既存のスキーマでこの状況を見つけて変更する必要はありません (チューニング時)。ただし、列にインデックスを作成する予定の場合は、NULL 可能となるように設計しないようにしてください。

もちろん例外もあります。たとえば、InnoDB は NULL 値を格納するために別のビットを使用するため、スパース データのスペース効率が優れていることは注目に値します。これは MyISAM には適用されません。

この本の説明には、いくつかの大きな問題が言及されています。ここでは、MyISAM の問題については触れず、InnoDB に焦点を当てて検討します。

  • NOT NULL が設定されていない場合、NULL が列のデフォルト値になります。必要がない場合は、NULL を使用しないようにしてください。
  • NULL を使用すると、インデックス、インデックス統計、値の計算が複雑になるなど、さらに多くの問題が発生します。インデックスを使用する場合は、列を NULL に設定しないようにする必要があります。
  • インデックス列の場合、ストレージ スペースの問題が発生し、追加の特別な処理が必要になり、さらに多くのストレージ スペースが占有されることになります。
  • スパース データの場合、スペース効率が向上します。スパース データとは、多くの値が NULL であり、列に NULL 以外の値を持つ行が少数しかない状況を指します。

デフォルト値

MySql の場合、NOT NULL にアクティブに設定されていない場合、データを挿入するときのデフォルト値は NULL になります。

NULL と NOT NULL で使用される空の値の意味は異なります。NULL は、この列の値が不明であると考えることができますが、空の値は、値はわかっているが空であると考えることができます。

たとえば、テーブル内のnameフィールドが NULL の場合、名前がわからないと想定できます。逆に、空の文字列の場合は、名前がないこと、つまり NULL 値であることがわかっていると想定できます。

ほとんどのプログラムでは、フィールドを NULL にする必要は特にありません。逆に、NULL 値はプログラム内でヌルポインターなどの問題を引き起こします。

MyBatisが使用されている現在のほとんどの状況では、デフォルト値が有効にならない問題や NOT NULL フィールドを追加することによって挿入エラーが発生する問題を回避するために、デフォルトで生成されたinsertSelectiveメソッドまたは完全に手動の挿入メソッドを使用することをお勧めします。

価値計算

不正確な集計関数

NULL 値を持つ列の場合、集計関数を使用するときに NULL 値は無視されます。

これでテーブルができました。name nameはデフォルトで NULL です。この時点で、 name count結果は 1 ですが、これは間違っています。

count(*)テーブル内の行数をカウントし、 count(name)はテーブル内の NULL 以外の列をカウントします。

= 無効

NULL 値を持つ列の場合、 =式を使用して判断することはできません。 nameに対する次のクエリは無効であり、 is NULL使用する必要があります。

他の値の操作

NULL とその他の値演算は NULL であり、式の値も NULL になります。

userテーブルの 2 番目のレコードのage NULL なので、 +1後も NULL のままです。Name name NULL なので、 concat操作後も結果は NULL のままです。

次の例をもう一度見てみましょう。NULL を使用した操作はすべて NULL になります。設計したフィールドが NULL で、誤ってさまざまな操作を実行した場合、結果はどうなるか想像してみてください。 。 。

個別、グループ化、順序付け

distinctおよびgroup by場合、すべての NULL 値は等しいとみなされ、 order by場合、昇順の NULL 値が最初にソートされます。

その他の問題

テーブルには名前を持つレコードが 1 つだけあります。この時点で、name !=aクエリすると、残りの 2 つのレコードが見つかるはずですが、期待した結果が一致しないことがわかります。

インデックス作成の問題

NULL フィールドがインデックスに与える影響を検証するには、 nameageにそれぞれインデックスを追加します。

クエリがNULLの場合はインデックスが使用できないという意見がネット上に多くありますが、これは正確ではありません。公式ドキュメント[3]によると、is NULLおよび範囲クエリを使用する場合、インデックスは正常に使用できます。実際の検証結果も同じようです。次の例を参照してください。

その後、テストのためにデータベースにいくつかのデータを挿入し続けました。NULL 列値の数が増えると、インデックスが無効になることがわかりました。

クエリ SQL の実行プロセスは、おおよそ次のようになることがわかっています。

まず、コネクタは指定されたデータベースに接続し、クエリ キャッシュにこのステートメントがあるかどうかを確認します。ある場合は、結果を直接返します。

キャッシュがヒットしない場合は、アナライザーが SQL ステートメントの構文と字句解析を実行して、SQL ステートメントが正当かどうかを判断する必要があります。

ここでオプティマイザーが登場し、どのインデックスをより合理的に使用するかが選択され、SQL ステートメントの具体的な実行プランが決定されます。

最後に、エグゼキュータはステートメントを実行し、権限があるかどうかを照会し、実行結果を返す責任を負います。

上記の簡単なテスト結果から、書籍に記載されているように、インデックス列に NULL がある場合、オプティマイザーはより複雑になり、インデックス選択を行う際の最適化がより困難になることがわかります。

収納スペース

データベース内のレコードの行も、最終的なディスク ファイルに行として保存されます。InnoDB には、 REDUNDANTCOMPACTDYNAMIC 、およびCOMPRESSED 4 つの行ストレージ形式があります。

InnoDB のデフォルトの行ストレージ形式はCOMPACTです。ストレージ形式を以下に示します。点線部分は存在しない場合があります。

可変長フィールド長リスト:フィールドが複数ある場合は逆順で格納されます。フィールドは1つしかないので、そこまで考慮する必要はありません。格納形式は16進数です。可変長フィールドがない場合は、この部分は必要ありません。

NULL 値リスト: レコード内の値が NULL の場合の保存に使用されます。NULL 値が複数ある場合、それらも逆順で保存され、8 ビットの整数倍である必要があります。8 ビット未満の場合、上位ビットは 0 で埋められます。1 は NULL を表し、0 は NULL ではないことを表します。両方とも NULL でない場合は、これが存在します。

ROW_ID: レコード行の一意の識別子。主キーが指定されていない場合は、自動的に生成された ROW_ID が主キーとして機能します。

TRX_ID: トランザクション ID。

ROLL_PRT: ロールバックポインター。

最後に、各列の値です。

ストレージ形式の問題を説明するために、テスト用のテーブルを作成します。このテーブルでは、 c1フィールドのみが NOT NULL であり、他のフィールドは NULL になることができます。

可変フィールド長リスト: c1c3フィールドの長さはそれぞれ 1 と 2 なので、16 進数に変換すると長さは0x01 0x02になり、逆順にすると0x02 0x01になります。

NULL値リスト:NULLを許容する列があるため、 c2,c3,c4それぞれ010です。反転後も同様です。同時に、上位ビットは0で埋められ、8ビットになります。結果は00000010です。

他のフィールドは今のところ無視します。最初のレコードの結果は当然ですが、ここではエンコード後の結果は考慮しません。

これは完全なデータ行の形式です。逆に、すべてのフィールドを NOT NULL に設定し、データa,bb,ccc,ddddを挿入すると、保存形式は次のようになります。

NULL 自体はストレージ スペースを占有しませんが、NULL が存在する場合は、フラグ スペースの余分なバイトを占有します。

記事参考資料:

https://dev.mysql.com/doc/refman/8.0/en/nullの問題.html
参考:https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
参考文献
行フォーマット
https://www.cnblogs.com/zhoujinyi/articles/2726462.html

MySQL フィールドで NOT NULL を使用する理由に関するこの記事はこれで終わりです。MySQL フィールドで NOT NULL を使用する方法の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL で not in を使用して null 値を含める問題を解決する
  • 設定操作からMySQLへのNULLが見つからない問題を解決する
  • MySQL の null と not null、null と空の値の違いの詳細な説明''''''''
  • MySQL でテーブルを作成するときの NULL と NOT NULL の使用方法の詳細な説明
  • MySQL の NOT IN 充填ピットの NULL 列の問題の解決方法
  • MySQL の null 可能フィールドは NULL に設定する必要がありますか、それとも NOT NULL に設定する必要がありますか?
  • MySQL クエリの空のフィールドまたは空でないフィールド (null または null ではない)
  • mysql は、含まれていない、左結合、IS NULL、NOT EXISTS の効率の問題のレコードです
  • MySQL の null 制約のケースの説明

<<:  Ubuntu で nginx を使用して WebDAV ファイル サーバーを構築する詳細なプロセス

>>:  ウェブデザインの概要

推薦する

CSS を使用して、画像に 3D の凸型と凹型のエフェクト (フレーム外に凸型、またはフレーム内に凹型) を実現します。

Ⅰ. 問題の説明: CSS を使用して画像の 3D 凸凹効果を実現します。 Ⅱ実施手順は以下のとお...

MySQLクエリ速度が遅く、パフォーマンスが低下する原因と解決策

1. データベースクエリの速度に影響を与えるものは何ですか? 1.1 データベースクエリ速度に影響を...

React リストバーとショッピングカートコンポーネントの使用の詳細な説明

この記事では、Reactリストバーとショッピングカートコンポーネントの具体的なコードを参考までに紹介...

MySQL の制限使用法とページングクエリステートメントのパフォーマンス分析の詳細な説明

使用制限クエリ ステートメントを使用する場合、多くの場合、データの最初の数行または中間行を返す必要が...

HTML4とHTML5の違い: 入力にフォーカス実装コードを追加する方法

html4:コードをコピーコードは次のとおりです。 <フォーム> <p>&l...

MySQLのスケジュールタスクが正常に実行できない原因の分析と解決

目次序文原因分析と解決策スケジュールされたタスクを迅速に実行する要約する序文データベースのスケジュー...

Windows の MySQL net start mysql MySQL サービスの起動エラーが発生する システムエラーの解決

目次1- エラーの詳細2-シングルソリューション2.1-ディレクトリ C:\Windows\Syst...

Vue で className として空の文字列を使用することはなぜ推奨されないのですか?

目次空の文字列 '' と null を比較するケース1: 空の文字列を使用する &#...

Linux での JDK と Tomcat のアップロードと設定に関する詳細なチュートリアル

準備1. 仮想マシンを起動する2. gitツールルートアカウントでログインルートアカウントを使用して...

波効果を作成するための CSS のトリック

純粋な CSS を使用して波の効果を実現することは、常に非常に困難でした。 波形曲線を実現するにはベ...

javascript:void(0) の意味と使用例

voidキーワードの紹介まず、void キーワードは JavaScript で非常に重要なキーワード...

node.js でマルチコア CPU を最大限に活用する方法

目次概要node.js でマルチコア CPU を最大限に活用する方法Node で子プロセスを作成する...

MySQL 5.7 以降のバージョンのダウンロードとインストールのグラフィック チュートリアル

1. ダウンロード1. MySQL公式サイトのダウンロードアドレス: https://downloa...

MySQLがOracleのnvlと同様の機能を持つことができるかどうかについての簡単な議論

isnullの代わりにifnullを使用するisnull は、null かどうかを判断するために使用...

Vue で親子コンポーネントの値を双方向バインドするために v-model を使用するときに発生する問題と解決策

目次シナリオ解決してみる解決するシナリオ今日、コンポーネントの双方向データバインディングにv-mod...