web-dev-qa-db-ja.com

MySQLテーブルでNULLを使用する場合

データベーステーブルのNULL値の意味的な意味は、falseや空の文字列 ''とは異なります。ただし、フィールドがNULL可能である場合のパフォーマンスの問題についてはよく読んでおり、NULLが実際には意味的に正しい場合は空の文字列を使用するようにアドバイスされています。

Null許容フィールドとnull値を使用するのに適切な状況は何ですか?トレードオフとは何ですか? NULLをまったく使用しないで、空の文字列、falseまたは0を使用して値がないことを示すことは賢明ですか?

[〜#〜]更新[〜#〜]

OK-''とNULLの意味の違い、およびNULLが適切なフィールド値である(パフォーマンスに依存しない)状況を理解しています。ただし、ヒントとなるパフォーマンスの問題について詳しく説明します。これは、シュワルツ、ゼイツェフ他による優れた「高性能MySQL」からのものです http://www.borders.co.uk/book/high-performance-mysql-optimization-backups-replication-and-more/ 857673 /

MySQLでは、null可能列を参照するクエリを最適化するのは困難です。これは、null可能列を参照することで、インデックス、インデックス統計、および値の比較がより複雑になるためです。 null可能な列はより多くのストレージスペースを使用し、MySQL内で特別な処理を必要とします。 null可能列にインデックスが付けられると、エントリごとに追加のバイトが必要になり、固定サイズのinded(単一の整数列のインデックスなど)がMyISAMで可変サイズの列に変換されることもあります。

詳細: Googleブックスのプレビュー

これはおそらく最も確実な答えです。第一線からのセカンドオピニオンと経験を探していました。

48

ただし、フィールドがNULL可能である場合のパフォーマンスの問題についてはよく読んでおり、NULLが実際には意味的に正しい場合は空の文字列を使用するようにアドバイスされています。

少しの間、Wordの選択について細心の注意を払います。

  • それが重要なパフォーマンス要因であったとしても、それはそれを作りません意味的に NULLの代わりに値を使用することが正しいです。 SQLでは、NULLにはセマンティックロールがあり、欠落または適用できない値を示します。特定のRDBMS実装におけるNULLのパフォーマンス特性は、これとは無関係です。パフォーマンスはブランドごと、またはバージョンごとに異なる場合がありますが、言語におけるNULLの目的は一貫しています。

いずれにしても、NULLのパフォーマンスが低いという証拠は聞いたことがありません。 null可能列がnull可能でない列よりもパフォーマンスが低いことを示すパフォーマンス測定への参照に興味があります。

私が間違っていたり、場合によっては当てはまらないと言っているわけではありません。ただ、怠惰な推測をするのは意味がないということです。科学は推測で構成されていません。再現可能な測定で証拠を示さなければなりません。

メトリクスはどのくらいによってもパフォーマンスが異なるため、それが心配する価値のあるものかどうかを判断できます。つまり、影響は測定可能でゼロ以外の値になる可能性がありますが、テーブルの適切なインデックス作成やデータベースキャッシュのサイズ変更などのより大きなパフォーマンス要因と比較しても、重要ではありません。

MySQLでは、NULLの検索はインデックスの恩恵を受けることができます。

mysql> CREATE TABLE foo (
  i INT NOT NULL,
  j INT DEFAULT NULL,
  PRIMARY KEY (i),
  UNIQUE KEY j_index (j)
);

mysql> INSERT INTO foo (i, j) VALUES 
  (1, 1), (2, 2), (3, NULL), (4, NULL), (5, 5);

mysql> EXPLAIN SELECT * FROM foo WHERE i = 3;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | foo   | const | PRIMARY       | PRIMARY | 4       | const |    1 |       | 
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

mysql> EXPLAIN SELECT * FROM foo WHERE j IS NULL;
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key     | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
|  1 | SIMPLE      | foo   | ref  | j_index       | j_index | 5       | const |    2 | Using where | 
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+

まだパフォーマンスの測定値ではないことに注意してください。 NULLを検索するときにインデックスを使用できることだけを示しました。空の文字列ではなくNULLを検索するときに、インデックスの利点があらゆるペナルティを覆い隠すと断言します(確かに測定していませんが、これは単なるStackOverflowです)。

NULLの代わりにゼロ、空白、またはその他の値を選択するのは、正しい設計上の決定ではありません。これらの値を列で重要な値として使用する必要がある場合があります。そのため、データ型の値のドメインの外にある値としてNULLが存在するので、整数や文字列などの値の全範囲を使用でき、さらに「上記の値のいずれでもない」ことを示す何かを持つことができます。 」

37
Bill Karwin

MySQLマニュアルには、実際には NULLの問題についての素晴らしい記事があります

それが役に立てば幸い。

この他にも見つかりました SOのNULLおよびパフォーマンスに関する投稿

11
Ólafur Waage

数値または日付でない限り、データベースでNULL値を許可しません。これを行う理由は、数値がゼロにデフォルト設定されるべきではない場合があるためです。これは非常に悪いことです。私は株式ブローカーの開発者であり、[〜#〜] null [〜#〜]との間には大きな大きな違いがあります。 COALESCEの使用は、デフォルト値をゼロに戻したくない場合でも、ゼロに戻したい場合に便利です。

MyVal = COALESCE(TheData, 0)

フラットファイルからデータの一括挿入を行うときは、フォーマットファイルを使用して、とにかく空の値を空の文字列に自動的に変換するデータのエントリを決定します。

日付のデフォルトは、私が信じる照合に依存して表示される可能性のある任意の値になりますが、私たちのデフォルトは1900のようなものにデフォルト設定されており、日付も非常に重要です。他のプレーンテキスト値はそれほど重要ではありません。空白のままにしておくと、通常は問題ありません。

5
Kezzer

一般に、属性が必要な場合はNot NULLとして定義され、省略できる場合はNULL可能として定義されます。

3
Jim Anderson

@ForYourOwnGoodが言ったように-「不明な」情報にはNullを使用する必要があります。例:お客様が登録時に入力する必要のあるフィールドが多数あり、それらの一部はオプションである場合。何らかの理由で、特定の顧客用にIDを予約したい場合があります。オプションのフィールドが空のままにしておくことが顧客によって本当に選択できるかどうかわからないので、最初に保存するときに、それらをNULL、つまり「不明」として設定する必要があります。行。顧客がフォームを送信し、すべての検証に合格した後、情報を保存すると、オプションフィールドは意図的に空のままになっていることがわかります。

これは、NULLを使用する良い例です。

2
user1105491

空の文字列は、NULLの代わりに使用しないでください。 NULLは、空の文字列が何かであり、内部に何もないため、何も表しません。 NULLは、別の値(NULLも含む)と比較すると常にfalseであり、NULLCOUNT関数で合計されません。

不明な情報を表す必要がある場合は、NULLの代わりはありません。

2
ForYourOwnGood

MySQLのNULLセマンティクスが完全に適切な場合があることを理解しています。

そうは言っても、彼らは特にテキストフィールドで真剣に邪魔をします。

これが実際の例です。

FileMakerデータベースからmysqlテーブルにデータをコピーしたいと思います。

「SELECT * from table where textfield <> 'test'」を実行すると、テキストフィールドがNULLの行は返されません。これはおそらくあなたが期待したり望んだことではありません。

whereクエリでnull可能なフィールドが単独で、またはANDの一部として使用されている場合、IS NULLテストが使用されない限り、NULLのエントリは決して返されません。 "where((textfield <>" test ")OR(textfield IS NOT NULL))"のように、醜いです。

したがって、この場合、フィールドをnullにできるようにしたくないでしょう。

ここでの問題は、Filemakerを使用して空の文字列をMySQLに挿入できないことです。これはNULLに変換され、列をnullにしないとエラーになります。 NULLを許可すると、mysqlへの転送は機能しますが、notクエリは意図したとおりに機能しません。

解決策は、テーブルを2回変更し、インポート後に既存のnullを空の文字列に変換し、テーブルをもう一度変更してnullを許可することです。ユーッチ!

いまいましいファイルメーカー。

1
Chuck Cochems

もちろん、主な利点は、あなたが言及したNULLの意味上の意味です。

それに加えて-そして、いつものように、ストレージエンジンに依存する場合がありますが、ドキュメントを確認してください-しかし、少なくとも一部のデータベースでは、NULLは通常の値よりもはるかに少ないスペースしか使用しません。たとえば、「varchar」列が20文字として宣言されていて、ほとんど入力されていない場合、空の文字列ではなくNULLにすることで、多くのディスク領域を節約できます。

NULLの使用に関するパフォーマンスの問題について聞いたことがありません。 NULLを間違って数えたが、パフォーマンスを上げなかったために、数を数え上げている人がいると聞いています。それが本当なら、ぜひ聞いてみたいです!

1
SquareCog

NULL列の意味は、多かれ少なかれ「このコンテキストには適用されません」です。私は通常、次の2つの場合にNULL列を使用します。

  • フィールドが適用されない場合(ブール列is_thirstyがあり、2つのデータセットを追加するとします。1つの人間と1つの石。人間の場合、is_thirstyをtrueまたはfalseに設定しますが、石の場合は、おそらくNULLに設定します。
  • 何かにフラグを立て、値とともにデータを保存する必要がある場合。在庫の終了日と同様に、a)在庫を変更できないことを指定し、b)在庫がいつ閉じられたかを指定します。 2つの列(closed_atおよびis_closed)、closed_at列を作成し、在庫セットを引き続き変更できる場合はNULLに設定しますが、クローズしたら日付を設定します。

基本的には、フィールドの空性が空のフィールドとは異なる固有のセマンティクスを持っているときにNULLを使用するという事実に要約されます。ミドルイニシャルがないのはそれだけです。決算日がないことは、在庫セットがまだ変更に対応できることを意味します。

NULL値は厄介な副作用をもたらす可能性があり、テーブルにデータを追加するのが困難になり、多くの場合、NULL値と空の文字列の寄せ集めになってしまう可能性があります。

また、NULLは何にも等しくありません。非常に注意しないと、クエリがいたるところにねじ込まれます。

個人的には、上記の2つのケースのいずれかが当てはまる場合にのみNULL列を使用します。空が値がないこと以外に意味がない場合は、空のフィールドを表すためにそれを使用することはありません。

1
pilif

クエリが正しく設計されていない限り(通常、これはNULLに関して非常に頻繁に発生する問題ではありません)、最近の自己尊重データベースエンジンは、NULLを適切に使用することによるペナルティを提供しないはずです。

データベース(NULLを含む)を意図したとおりに使用することに最初に注意を払う必要があります。次に、最適化の結果が発生するかどうか、発生するかどうかを心配します。

SQLの複雑さと正確さの両方における不適切にNULL化された列値の累積的な影響は、ほぼ確実に、マザーDBMSをだますことの利点を上回ります。その上、それはあなたの頭だけでなく、あなたが何をしようとしていたのかを理解しようとする人の頭を台無しにするでしょう。

0
dkretz

Oracleのような一部のデータベースでは、MySQLでsomethinkgが当てはまる場合があります。

  • Nullはインデックス付けされないため、null値を探すことがボトルネックになる可能性があります。
  • 行の末尾のnullはスペースを節約します。
0
FerranB