うわー、「パフォーマンスが低下するため、必要がない場合はNULLを許可しない」という正解は、どういうわけか最後に評価された回答です。私はそれを賛成し、詳しく説明します。RDBMSが非スパース列にNULLを許可する場合、その列はビットマップに追加され、個々の行の値がNULLかどうかを追跡します。そのため、すべての列でNULLが許可されていないテーブルの列にNULL機能を追加すると、テーブルを保存するために必要なストレージ領域が増加します。さらに、ビットマップの読み取りと書き込みをRDBMSに要求しているため、すべての操作のパフォーマンスが低下します。
さらに、多くの場合、NULLを許可すると3NFが壊れます。私は同僚の多くのように3NFにこだわりはありませんが、次のシナリオを検討してください。
Personテーブルには、DateOfDeathと呼ばれる、null許容の列があります。人が死亡した場合、DateOfDeathが入力され、そうでない場合はNULLのままになります。IsAliveと呼ばれる、null不可のビット列もあります。この列は、人が生きている場合は1に、人が死んでいる場合は0に設定されます。ストアドプロシージャの大部分はIsAlive列を使用し、DateOfDeathではなく人が生きている場合にのみ気にします。
ただし、IsAlive列は、DateOfDeathから完全に派生できるため、データベースの正規化を中断します。ただし、IsAliveは大部分のSPに組み込まれているため、簡単な解決策は、DateOfDeathをNULL不可にし、その人物がまだ生きている場合にデフォルト値を列に割り当てることです。DateOfDeathを使用するいくつかのSPは、IsAlive列を確認するように書き換えることができ、人物が生きていない場合にのみDateOfDeathを尊重します。繰り返しますが、SPの大部分はIsAlive(ビット)のみを考慮し、DateOfDeath(日付)ではなく、このパターンを使用するとアクセスが大幅に高速化されるためです。
すべてのスキーマでNULLのないNULL許容列を検索するための便利なT-SQLスクリプトは次のとおりです。
select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
from sys.columns c
inner join sys.tables t ON c.object_id = t.object_id
inner join sys.schemas s ON s.schema_id = t.schema_id
where c.is_nullable = 1 AND c.is_computed = 0
order by s.name, t.name, c.name;
実稼働データベースのコピーでこれを実行すると、実際にはNULLを持たないNULLを許可するようにマークされた列の開発者を見つけることができます。これらの大半はNOT NULLとしてマークできるため、パフォーマンスが向上し、ストレージスペースが減少します。
すべてのテーブルのすべてのNULLを削除することは不可能であり、クリーンなデザインを維持することはできませんが、可能な限り多くのNULLを削除することには大きな利点があります。オプティマイザーはこの情報を使用してはるかに高速に動作し、テーブル内のすべてのNULLを削除できる場合、かなりの量のストレージスペースを取り戻すことができます。
パフォーマンスはDBAがそれほど考慮しているものではないことはわかっていますが、ソリューションでは限られた量のメモリとプロセッサパワーしか投入できません。 。
また、これは真のRDBMS専用であり、回答の技術的な部分はSQL Serverに基づいていることに注意してください。nullのないnull許容列を検索するためにリストされているT-SQLもSQL Serverからのものです。