6

私はいくつかの可能なアプローチを見てきました(いくつかのデータベースエンジンではそれらのいくつかは同義語です):

  1. TINYINT(1)
  2. BOOL
  3. BIT(1)
  4. ENUM(0,1)
  5. CHAR(0)NULL

PHPでサポートされているすべての主要なデータベースエンジンに注意する必要がありますが、参考として、他のエンジンにも注意してください。

読書に最適なデザインを求めています。たとえば、WHERE条件のフラグフィールドを使用したSELECTing、またはGROUPBYフラグ。パフォーマンスは、ストレージスペースよりもはるかに重要です(サイズがパフォーマンスに影響を与える場合を除く)。

そして、いくつかの詳細:

テーブルを作成している間、それがスパースになるかどうかはわかりません(ほとんどのフラグがオンかオフか)が、後でテーブルを変更することができるので、それを知っていれば最適化できるものがある場合は、了解しました。

また、行ごとにフラグが1つ(または少数)しかない場合と、フラグが多数(または多数)ある場合に違いが生じる場合は、注意が必要です。

ところで、私はSOのどこかで次のことを読みました:

booleanを使用すると、tinyintを使用するのと同じことができますが、意味的に意図を伝えるという利点があり、それは価値があります。

私の場合、各テーブルはアプリケーションのクラスによって表され、すべてがクラスで明示的に定義され、十分に文書化されているため、何の価値もありません。

4

3 に答える 3

6

この回答はISO/IEC / ANSI標準SQLに対するものであり、より優れたフリーウェアのふりをするSQLが含まれています。

最初の問題は、1つではなく、2つのカテゴリを識別したため、合理的に比較できないことです。

A.カテゴリー1

(1)(4)および(5)には複数の可能な値が含まれ、1つのカテゴリーです。WHERE句では、すべてを簡単かつ効果的に使用できます。それらは同じストレージを持っているので、ストレージも読み取りパフォーマンスも問題ではありません。したがって、残りの選択肢は、列の目的のための実際のデータ型に基づいています。

ENUMは非標準です。より良いまたは標準的な方法は、ルックアップテーブルを使用することです。次に、値は非表示ではなくテーブルに表示され、任意のレポートツールで列挙できます。ENUMの読み取りパフォーマンスは、内部処理のために小さな打撃を受けます。

B.カテゴリー2

(2)と(3)は2つの値の要素です:True / False; 男女; 生死。そのカテゴリはカテゴリ1とは異なります。データモデルと各プラットフォームの両方での処理は異なります。BOOLEANはBITの同義語であり、同じものです。法的に(SQLに関して)、すべてのSQL準拠プラットフォームで同じように処理され、WHERE句で問題なく使用できます。

パフォーマンスの違いはプラットフォームによって異なります。SybaseとDB2は、最大8ビットを1バイトにパックし(ここではストレージは重要ではありません)、2の累乗をオンザフライでマップするため、パフォーマンスは非常に優れています。Oracleはバージョンごとに異なることを行い、モデラーがパフォーマンスの問題を克服するためにBITの代わりにCHAR(1)を使用するのを見てきました。MSは2005年までは問題ありませんでしたが、結果が予測できないため、2008年にはそれを破りました。したがって、簡単な答えは、CHAR(1)として実装することです。

もちろん、8つの別々の列を1つのTINYINTにパックするなどのばかげたことをしないことを前提としています。これは深刻な正規化エラーであるだけでなく、コーダーにとっては悪夢です。各列を離散し、正しいデータ型に保ちます。

C.複数のインジケーターとNULL可能列

これは、(A)および(B)とは関係がなく、独立しています。列が正しいデータ型とは、所有している数とNullableかどうかによって異なります。Nullableは、(通常)列がオプションであることを意味します。基本的に、モデリングまたは正規化の演習は完了していません。機能従属性はあいまいです。正規化の演習を完了すると、Null許容列やオプションの列はなくなります。それらは特定の関係に対して明らかに存在するか、または存在しません。これは、スーパータイプ-サブタイプの通常のリレーショナル構造を使用することを意味します。

確かに、それはより多くのテーブルを意味しますが、Nullはありません。Enterpise DBMSは、テーブルや結合が増えても問題はありません。これが最適化されているためです。正規化されたデータベースは、正規化されていないデータベースや非正規化されたデータベースよりもはるかに優れたパフォーマンスを発揮し、「リファクタリング」なしで拡張できます。サブタイプごとにビューを提供することで、使いやすくなります。

このテーマに関する詳細情報が必要な場合は、この質問/回答をご覧ください。モデリングについてサポートが必要な場合は、新しい質問をしてください。あなたの質問のレベルでは、5NFに固執することをお勧めします。

D.ヌルのパフォーマンス

これとは別に、パフォーマンスが重要な場合は、Nullを除外します。各Nullable列は可変長として格納されます。行/列ごとに追加の処理が必要です。エンタープライズデータベースは、このような行に対して「遅延」処理を使用して、ログなどが固定行を妨げることなくキューを移動できるようにします。特に、インデックスで可変長列(Nullable列を含む)を使用しないでください。アクセスごとに解凍する必要があります。

E.投票

最後に、私はこの質問のポイントが世論調査であるとは思いません。技術的な回答や意見さえも得られるのは十分公平ですが、投票は人気コンテスト用であり、SOの回答者の技術的能力は非常に広範囲にわたるため、最も人気のある回答と最も技術的に正しい回答は2つの異なるものになりますスペクトルの終わり。

于 2010-12-27T02:32:43.057 に答える
1

私はこれがあなたが望む答えではないことを知っていますが、最も極端な特別な場合を除いて、違いは本当に無視できます。そして、そのような特定のケースでは、データ型を切り替えるだけではパフォーマンスの問題を解決するのに十分ではありません。

たとえば、データ型の変更を大幅に上回るいくつかの選択肢があります。もちろん、それぞれに欠点があります。

200個のオプションのフラグがあり、多数の行に対して一度に最大1〜2個のクエリを実行する場合、各フラグを独自のテーブルに含めることでパフォーマンスが向上します。データが本当にまばらである場合、これはさらに良くなります。

200個の必須フラグがあり、単一レコードのフェッチのみを実行する場合は、それらを同じテーブルに配置する必要があります。

フラグのセットが少ない場合は、ビットマスクを使用してそれらを1つの列にパックできます。これは、ストレージの面で効率的ですが、個々のフラグを(簡単に)クエリすることはできません。もちろん、フラグがNULLになる可能性がある場合、これは機能しません...

または、創造性を発揮して「ジャンクディメンション」の概念を使用することもできます。この概念では、200個すべてのブールフラグが列として表された個別のテーブルを作成します。フラグ値の個別の組み合わせごとに1つの行を作成します。各行は、マスターレコードで参照する自動インクリメントの主キーを取得します。出来上がり、マスターテーブルには200列ではなく1intが含まれるようになりました。ハッカー天国、DBAの悪夢。

私が言いたいのは、どちらが「最高」であるかを議論するのは興味深いことですが、他にももっと重要な懸念事項があるということです(あなたが引用したコメントなど)。実際のパフォーマンスの問題が発生した場合、データ型が問題でも解決策でもないという理由だけで。

于 2010-12-27T00:08:30.270 に答える
0

上記のいずれも問題ありません。適切にサポートされている場合は、個人的に使用することを好みます。BOOLこれは、あなたの意図を最もよく伝えるためですが、使用は避けENUM(0,1)ます。

の最初の問題ENUMは、値が文字列である必要があることです。0数字のように1見えるので、プログラマーはそれに数字を送る傾向があります。

の2番目の問題ENUMは、間違った値を送信すると、デフォルトで最初の列挙になり、一部のデータベースではエラーを示さないことです(MySQLを見ています)。これにより、最初の問題がさらに悪化します。これは、誤って送信する1代わりに"1"値を保存してしまうため、"0"非常に直感に反するためです。

これがすべてのデータベースエンジンに影響を与えるとは思いませんが(わからない、すべてを試したわけではありません)、十分に影響を与えるので、回避することをお勧めします。

于 2010-12-27T01:11:07.710 に答える