Tinyint vs Bit?


81

ここで宗教戦争に触れたくはありませんが、データベースでブール値を表現する方法については2つの考え方があるようです。bit適切なデータ型であると言う人もいれば、tinyintより良いと主張する人もいます。

私が知っている唯一の違いはこれらです:

  • bit:ストレージサイズは1ビット、可能な値は0または1です
  • tinyint:ストレージサイズは1バイト、可能な値は0〜255です

ブール値を表す必要がある場合、どのデータ型が適していますか?あるtinyint価値が余分なオーバーヘッド「念のために」あなたは値> 1に必要ですか?


1
「万が一に備えて」は、かなり流動的なデータベース設計のようです。すべてをNVARCHAR(MAX)として保存し、すべてのベースをカバーしてみませんか?
スチュアートエインズワース2018

TinyIntが私の好みです。次に、フィールドに対して集計カウントを行う場合、それをキャストする必要はありません。また、一部のフロントエンド言語は他の言語とは少し異なって解釈し、TinyIntを使用すると、検証チェックがすべてのフロントエンド言語に対してユニバーサルになります。
グレゴリーハート

phpMyAdminのビットで奇妙なことに遭遇しました。フィールドをNULLにしてデフォルト値を設定しないように指示すると、デフォルトでNULLではなく<em> NULL </ em>になります。tinyint btwの+ 1
VörösAmadea19年

フォームをインポートする場合、csvファイル1はtinyint(1)の場合は機能しますが、bit(1)の場合は、b'1 'に置き換える必要があります
Rajat

回答:


90

テーブルにビット列を追加すると、1ビットだけでなく、各レコードの1バイト全体を占有します。2番目のビット列を追加すると、同じバイトに格納されます。9番目のビット列には2バイト目のストレージが必要です。1ビット列のテーブルには、ストレージのメリットはありません。

Tinyintとbitはどちらも機能させることができます。私は両方をうまく使用しており、強い好みはありません。


それは非常に有益なコメントであり、あなたの評判は非常に良いですが、それをサポートするための参照はありますか?それは実装の詳細ですか、それともすべてのエンジンが同じように処理しますか?
Jon z

3
@JonzMySQLについてはこちらをご覧ください。
shmosel 2016年

@shmoselの参照から、1ビット(1)列が1バイトを占めることは非常に明白ですが、8ビット(1)列が同じバイトをとるまで、2、3、4 ...ということはそれほど明確ではありません。私はそれをオンラインで検索しましたが成功しませんでした。それも参考にできますか?テーブルに必要な4つのブール列がある場合、ストレージスペースを節約するためにtinyint(1)の代わりにbit(1)列を使用する価値があるかどうかを知りたいだけです。ありがとうございました。
assensi

@assensi良い点。フィールドのBIT(n)代わりにいつでもシングルを使用できnます。または、通常INTを使用して、各ブール値をビットとして格納することもできます。ただし、別々のフィールドを使用する場合TINYINT、通常 、MySQLよりも優先BITれると思います。
shmosel

19

ビット...あなたが「true / false /ファイルが見つかりません」クランでない限り

参照を取得しなかった場合...

また、Linq2SQLの場合、ビットはtrue / falseで機能するため、プログラミングが容易になります。両方に利点があります。

また、考慮すべきプログラミングのメンテナンスもあります。あなた(またはジュニアインターンプログラマー)が2、3、25、41、167、200などを使用するとどうなりますか?それはどこに文書化されていますか?ビットは自己文書化されており、かなり普遍的です。


11
ビットはnull許容であるため、T / F / FNFを引き続き使用できます。
オースティンサロネン

3
そして、NULLがFNFに等しいことはどれほど悪ですか?:) thedailywtfに本当にふさわしい!
ジョンルディ

@Pratik問題がNULLであるということは、データベースに値がないことを意味します。ファイルが見つからないという意味ではありません。これを行うと、文書化が難しく混乱を招く状態を行に暗黙的にエンコードし始めます。アイテムのテーブルを持っているようなものです。アイテムが販売されたかどうかを確認するにはどうすればよいですか?販売価格、販売日、購入者の名前などがあるかどうかを確認できます。または、チェック制約を使用してそれらすべてを適用し、販売されたアイテムのビットフィールドを作成することもできます。
codeMonkey 2015

15

必要に応じてビットを使用します。意味的に正しいタイプ(セマンティクスカウント!)であることに加えて、単一の行(とにかくSQL Server上)の複数のビットフィールド(最大8)を1バイトのストレージに統合できます。8番目以降は、次の8に追加のバイトが必要になります。

参照:




2

ブール値は、定義上、2つの値のみを許可します。なぜこれに1ビット以上のものが必要なのですか?3つ(またはそれ以上)の状態ロジックが必要な場合は、より大きなデータ型を使用しますが、標準のブール論理のビットフィールドを使用します(実際に使用します)。


2

ビットを使用するのは、チェック制約を使用する手間が省け、ORMがビットをnull許容ブール値(C#)に自動的に変換するためです。これは、コーディングすると非常に高く評価されます。


2

Falseのゼロスペース

どちらを選択しても、NULL代わりに設定でき、余分なスペース0は必要ありません(データベースにはほとんどの場合NULL、すべての行のすべてのフィールドにフラグがあり、そこに座っているだけです。詳細はこちら)。また、デフォルト/最も可能性の高い値がfalseであることを確認すると、さらに多くのスペースを節約できます。

真のスペース

表す値にはtrue、フィールドタイプで定義されたスペースが必要です。を使用BITすると、テーブルにそのような列が複数ある場合にのみスペースが節約されます。これは、8フィールドTINYINTごとに1バイトを使用するためです(フィールドごとに1バイトを使用する場合とは異なります)。

TINYINT余分な列の束を管理することを心配せずに8値ビットマスクをカスタマイズできるという利点があり、検索は理論的に高速です(単一の整数フィールドと複数のビットフィールド)。ただし、順序が遅い、クロスインデックス機能が優れている、フィールド名がないなどの欠点があります。私にとって、これが最大の損失です。データベースでは、どのビットがどのビットマスクで何を実行したかを記録するための外部ドキュメントが必要になります。

いずれの場合も、TEXTフィールドを使用してブール値またはそれらのセットを格納する誘惑を避けてください。テキストの検索はサーバーにとってはるかに多くの作業であり、「オン、オフ、オフ」などの任意の命名スキームは相互運用性を損なう可能性があります。


1

ビット(SQL Server 2k5)でグループ化を試したところ、問題なく動作しました。アプリケーションに正しいデータ型を使用するのが好きです。それが真/偽のフィールドである場合、ビットは私が使用するものです...


1

これらの理論的な議論はすべて素晴らしいですが、実際には、少なくともMySQLを使用していて、実際にはSQLServerでも使用している場合は、ブール値の非バイナリデータを使用するのが最善です。これは、作業が簡単であるという単純な理由からです。 'データの出力、クエリなど。MySQLとSQLServerの間で相互運用性を実現しようとしている場合(つまり、2つの間でデータを同期する場合)は、BITデータ型の処理が2つで異なるため、特に重要です。したがって、実際には、数値データ型を使用する場合は、煩わしさが大幅に軽減されます。MySQLには、TINYINT(1)として格納されるBOOLまたはBOOLEANを使用することをお勧めします。MySQLWorkbenchとMySQLAdministratorがBITデータ型を表示する方法でさえ、良くありません(これはバイナリデータの小さな記号です)。


1

上記で見たとは思いませんが、BIT列(MIN、MAX、特にSUMなど)を集約できないという問題があります。2008を使用してテストしたところ、問題はまだ残っています。これが私が最近tinyintを使用する最大の理由です-もう1つは、tinyintのスケーリング方法が好きです-「2値」ビットフラグが突然より多くの可能な値を必要とするとき、それは常に苦痛です。


1
それらを別のデータ型にキャストすることで集約できます-なぜtrue / falseを合計する必要があるのでしょうか?
マーティンスミス

2
私たちは頻繁に1つのフィールドでグループ化し、結果ごとに各グループに当てはまる別のフィールドの数を合計します。合計の代わりに、結果全体をコードに返し、そこでループすることで、クライアントに1000倍以上のデータを返すことがあります。 。しかし、キャストはそれを排除するので、それは問題ではありません。
デヴィッド・Martenssonから

0

すべてのテーブルをint「vector」フィールドで作成します。次に、そのフィールドを、任意の目的に割り当てることができる32ビットのコレクションとして使用します。(状態のセットにビットのグループを使用する可能性があります)。忘れた場合にフラグフィールドを追加し続ける必要がなくなります。


2
難読化とも呼ばれます。または、一般の人にとっては、「メンテナンスの悪夢」です。
ロバートC.バース

6
すべてのテーブルを単一のTEXT列にして、すべてをコンマ区切りで配置することができます。そうすれば、データモデルを変更する必要はありません。
トムH

1
やや独特の環境があります。非常に大きなデータセットと49の稼働時間があるため、テーブルの変更はかなり禁止されています(レプリケーションが関係する場合の2倍)。一元化された場所ですべてのビットを追跡するため、メンテナンスの問題を回避できます。
ジョー

0

@Kevin:group byビットフィールドで使用できると思います(SQL Server 2005):

declare @t table (
    descr varchar(10),
    myBit1 bit, 
    myBit2 bit
)
insert into @t values ('test1', 0, 1)
insert into @t values ('test2', 1, 0)
insert into @t values ('test3', 1, 1)
insert into @t values ('test4', 0, 0)

select myBit1, count(myBit1) from @t group by myBit1
select myBit2, count(myBit1) from @t group by myBit2

結果:

myBit1 
------ -----------
0      2
1      2

myBit2 
------ -----------
0      2
1      2

0

TinyIntが私の好みです。次に、フィールドに対して集計カウントを行う場合、それをキャストする必要はありません。また、一部のフロントエンド言語は他の言語とは少し異なって解釈し、TinyIntを使用すると、検証チェックがすべてのフロントエンド言語に対してユニバーサルになります。



-2

「T」または「F」でchar(1)を使用するのが好きです。はい、他の値で悪用される可能性がありますが、少なくとも、ビット値またはバイナリ値の操作が難しいレポートやその他の場所で簡単に表示できます。


2
「T」と「F」のみを許可するように、列に制約を簡単に追加できます(そしてそうすべきです)。そうは言っても、レポートレイヤーはデータベースから完全に分離されている必要があります。列の表示方法だけを目的としてデータベーススキーマを変更しないでください。
トムH

ダリルに同意します。一般的なRDBMSシステムでブール型がサポートされていないことを考えると(ここではMySQLだけではありません)、T / F(実際にはY / Nが好きです)の方がはるかに読みやすくなっています。トムHのコメントには原則的に同意しますが、読みやすさは彼の功績よりもはるかに重要だと思います。データベース開発者は、他の誰かのコードを変更するときにフロントエンドを見ません!また、開発者が1と0をどちらの方向と見なすかは必ずしも明確ではありません。私たち全員がそれを「適切な」昔ながらの方法で行っていたとしたら、私たちは-10を表すために、そして偽を表すために使用するでしょう。
cartbeforehorse 2012年

以前のコメントに、MySQLがCHECK制約をサポートしていないように見えることを追加する必要があります。これは、列にアルファベットの他の文字が入力されるのを防ぐことができないため、T / Fオプションを複雑にします。よくない。
cartbeforehorse 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.