リレーショナルデータベースは、各列に定義済みのデータ型を設定することで何が得られますか?


44

私は今、SQLデータベースを使用していますが、これは常に興味をそそりますが、Google検索はあまり現れません。なぜ厳密なデータ型なのでしょうか?

たとえば、バイナリデータとプレーンテキストデータの区別が重要であるなど、いくつかの異なるデータ型がある理由を理解しています。バイナリデータの1と0をプレーンテキストとして保存するのではなく、バイナリデータを独自の形式で保存する方が効率的であることを理解しています。

しかし、私理解していないのは、非常に多くの異なるデータ型を持つことの利点です:

  • なぜmediumtextlongtexttext
  • なぜdecimalfloatint

「この列のエントリにはプレーンテキストデータが256バイトしかありません」とデータベースに伝えることの利点は何ですか。または「この列には最大16,777,215バイトのテキストエントリを含めることができますか?」

パフォーマンス上のメリットはありますか?もしそうなら、手作業の前にエントリーのサイズを知ることがパフォーマンスに役立つのはなぜですか?それとも、まったく別のものですか?


2
この質問はすでにここにあるはずだと思っていましたが、サイトを検索しましたが、有用なものは見つかりませんでした。
ジョンドー

1
非常に関連性の高い:joelonsoftware.com/2001/12/11/back-to-basics
8bittree

6
あなたは明確な持っていなかった場合はdecimalfloat、およびint種類を、何を期待1 / 3しますか?どう1.0 / 3.0?それで割るとcolumnAcolumnB期待した結果が得られると確信できますか?
アンドリューは、モニカを復活させる

2
@johndoe必要になるとは思いませんが、非常に便利です。店舗の在庫が月間予想売上の5%を下回ってはならないという制約を適用するとします。または、各部門の合計予算が合計予算の20%を超えないようにする必要があります。また、同じデータベースを使用する複数のアプリケーションで同じ方法で計算したい計算列を作成することもできます。
アンドリューは、モニカを復活させる

2
SQLiteは列ごとに定義済みの型を設定しない ことに注意してください。「SQLiteは「型なし」です。つまり、その列の宣言されたデータ型に関係なく、任意の種類のデータを任意のテーブルの列に格納できます。 "
プライム

回答:


50

SQL静的に型付けされた言語です。これは、変数(この場合はフィールド)がどのタイプであるかを知ってからでなければ使用できないことを意味します。これは動的に型付けされた言語の反対であり、必ずしもそうではありません。

コアでは、SQLは、リレーショナルデータベースエンジンでデータを定義する(DDL)およびデータにアクセスする(DML)ように設計されています。静的型付けは、このタイプのシステムに動的型付けよりもいくつかの利点があります。

  • 特定のレコードにすばやくアクセスするために使用されるインデックスは、サイズが固定されている場合に非常にうまく機能します。おそらく複数のフィールドを持つインデックスを利用するクエリを考えてみましょう:データ型とサイズが事前にわかっている場合、述語(WHERE句またはJOIN基準)をインデックス内の値と非常に迅速に比較し、必要なレコードをすばやく見つけることができます。

  • 2つの整数値を考えます。動的型システムでは、サイズが可変である場合があります(Java BigIntegerやPythonの組み込み任意精度整数を考えてください)。整数を比較したい場合、まずビット長を知る必要があります。これは整数比較の側面であり、現代の言語ではほとんど隠されていますが、CPUレベルでは非常に現実的です。サイズが固定されており、事前にわかっている場合、ステップ全体がプロセスから削除されます。繰り返しになりますが、データベースは可能な限り迅速に無数のトランザクションを処理できるはずです。スピードが重要です。

  • SQLは1970年代に設計されました。マイクロコンピューティングの初期の頃は、メモリは貴重でした。データを制限することで、ストレージ要件を抑えることができました。整数が1バイトを超えて成長しない場合、なぜより多くのストレージを割り当てるのですか?それは、限られた記憶の時代の無駄なスペースです。現代でも、これらの余分な無駄なバイトは、CPUのキャッシュのパフォーマンスを合計して殺す可能性があります。これらは、小さな開発環境だけでなく、毎秒数百のトランザクションを処理するデータベースエンジンです。

  • 限られたストレージのラインに沿って、メモリ内の単一ページに単一レコードを収めることができると便利です。1ページを超えると、ページミスが多くなり、メモリアクセスが遅くなります。新しいエンジンには、これを問題の少ないものにするための最適化がありますが、まだあります。データのサイズを適切に設定することにより、このリスクを軽減できます。

  • さらに現代では、SQLを使用してORMまたはODBCまたは他のレイヤーを介して他の言語にプラグインします。これらの言語の一部には、強力で静的な型を要求する規則があります。動的に型付けされた言語は静的な型を他の方法よりも簡単に処理できるため、より厳しい要件に準拠することが最善です。

  • 上記のように、データベースエンジンはパフォーマンスのために静的型付けを必要とするため、SQLは静的型付けをサポートします。

興味深いことに、厳密に型指定されていない SQLの実装があることに注意してください。SQLiteは、おそらくこのようなリレーショナルデータベースエンジンの最も一般的な例です。この場合も、単一システム上でシングルスレッドで使用するように設計されているため、パフォーマンスの懸念は、たとえば1分あたり数百万のリクエストを処理するエンタープライズOracleデータベースほど顕著ではありません。


SQLiteには、数値データとテキストデータを区別するデータ型がありますが、データストレージの5つの「クラス」のみがあります。sqlite.org
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner私は知っていますが、SQL Server、Oracle、PostgreSQLなどのエンジンほど厳密ではありません。

SQLは静的に型付けされるだけでなく、チェック制約が存在するため、洗練型を効果的にサポートします。
ガーデンヘッド

4
最初の箇条書きでは暗示されていますがIndexes、より基本的には次のとおりです。データ型を使用すると、データベースエンジンがデータを理解し、比較を行うことができます(より大きい/小さい数値、早い/遅い日時、アルファベットの前後)、したがって、並べ替えとクエリが可能になります
バジルブルク

サイズが重要な場合...そしてSQLが事前に知る必要がある場合...「Zillion」トランザクションの正確なサイズは何ですか?
WernerCD

24

最初:プレーンテキストはバイナリです(UTF8またはASCII文字「0」と「1」でさえなく、実際のオン/オフビットです)

とはいえ、いくつかの理由は次のとおりです。

  • ビジネス/デザインの制約: PERSONテーブルのHEIGHT列に番号7626355112を許可するのは間違っています。INVOICEのDATE列で「Howya」を許可するのは間違っています。
  • エラーが発生しにくいコード:日付列から取得したデータが実際に日付であることを確認するためのコードを記述する必要はありません。列の型が動的である場合、列の読み取り時に多くの型チェックを行う必要があります。
  • 計算効率:列がINTEGER型であり、SUM()である場合、RDBMSは浮動小数点演算を適用する必要はありません。
  • ストレージ効率:列がVARCHAR(10)であることを指定すると、RDBMSがより正確にスペースを割り当てることができます。
  • 参照整合性と単一性:テーブルのPK(またはFK)は、浮動小数点の等価性が難しいため、浮動小数点数を許可するべきではありません。したがって、文字や整数などの非浮動型で宣言する必要があります。
  • 動的(厳密ではない)列型(SQLite)のRDBMSが存在します。文句を言わずに、事実上すべてを任意の列に挿入できるようにしながら、「タイプアフィニティ」の概念を使用します。ここでは説明しないトレードオフがあります。この質問をご覧ください。

8

特定のフィールドに0から256文字のテキストを含めることができることがわかっている場合は、データベースが書き込まれている基になるコードが固定サイズのレコードを割り当てて使用できるようにするため、256バイトのブロックを割り当てて格納できます。

これにより、ユーザーの入力時に追加のストレージを割り当てる必要がなくなります。たとえば、特定のフィールドは常にレコードからxバイトを開始するため、そのフィールドでの検索または選択は各レコードにxバイトを常にチェックすることがわかっています。


場合にのみ、すべての答えは、この簡潔とする-ポイント...かもしれない
ダレン・リンガー

6

データベースの列に定義済みの型が与えられると、通常、型はビット単位で特定のサイズを持つように定義されます。結果として:

1)データベースエンジンがテーブル内の行をトラバースするとき、各レコードの終了位置を決定するために高度な解析を行う必要はありません。各行がたとえば32バイトで構成されていることを知ることができます。次のレコードでは、現在のレコードの場所に32バイトを追加するだけで十分です。

2)行内のフィールドを検索する場合、何も解析せずにそのフィールドの正確なオフセットを再度知ることができるため、列ルックアップは潜在的にコストのかかるデータ処理ではなく、単純な算術演算です。


固定長フィールドは、レコード長とフィールドオフセットが一貫しているため、処理を効率化できますが、可変長フィールドは、レコード長とフィールドのオフセットが異なるため、これらの利点を無効にすることができます。同様に、レコードレベルの圧縮では可変長レコードが生成されるため、特定のレコードの場所を単純に計算することはできません。
-Zenilogix

これは事実であり、その理由から可変長フィールドを避けることは長い間一般的なアドバイスでした。大手プレイヤーがどのようにそれを行うかはわかりませんが、エンジンに可変幅フィールドをユーザーに表示されないテーブルまたはメモリブロックに格納させることで、固定長の利点の一部を取り戻すことができるようですこれらのフィールドのプライマリテーブル表現は、(固定幅)「ポインタ」です。可変長フィールドのフルスキャンを最初から定期的に実行する必要があることを考慮すると、間接化のパフォーマンスヒットは固定幅を維持する価値があるかもしれません。
UserNotFound

3

DBMSに静的データ型がある理由を尋ねました。

  1. ルックアップの速度。DBMSのポイントは、プログラムにロードできるよりもはるかに多くのデータを保存することです。「過去10年間に世界で発生したすべてのクレジットカードスリップ」を考えてください。このようなデータを効率的に検索するには、固定長のデータ型が役立ちます。これは、日付スタンプや口座番号などの構造化データに特に当てはまります。事前に何を扱っているかがわかっている場合、効率的なインデックスにロードする方が簡単です。

  2. 整合性と制約。データ型が固定されている場合、データをクリーンに保つのが簡単です。

  3. 歴史。RDBMSは、コンピューターのRAMが数メガバイトしかなく、テラバイト規模のストレージが非常に高価だったときに開始されました。テーブルの各行に1ダースのバイトを保存すると、そのような状況では数千ドルと時間を節約できます。

  4. 顧客ベースの呪い。今日のRDBMSは、非常に複雑で高度に最適化されたソフトウェアパッケージであり、数十年にわたってデータを蓄積してきました。彼らは成熟しています。彼らが働きます。大規模なデータ損失につながるRDBMSクラッシュは、ごく最近ではほとんどありません。より柔軟なデータタイピングシステムを備えたものに切り替えることは、ほとんどの組織にとってコストやリスクに見合うものではありません。

類推:都市の地下鉄システムが、より狭いレールゲージでより良く(静かで、高速で、電力効率が高い)動作することは、盲目的に明白かもしれません。しかし、これらの改善を実現するために、ニューヨーク市の地下鉄システムのすべてのレールをどのように変更しますか?そうではないので、持っているものを最適化します。


3

一般に、保存する内容についてデータベースに詳細に伝えるほど、ディスクに割り当てる容量や取得時に割り当てるメモリ量など、そのデータに関連するさまざまなパフォーマンスメトリックを最適化しようとすることができます。 。

なぜミディアムテキスト、ロングテキスト、テキストなのですか?

どのデータベースを使用しいるかわからないので、推測する必要があります。これらのデータ型のうち2つには上限があり、1つには上限がないと思います。上限のあるテキストにデータ型を使用すると、データベースに各レコードに必要なストレージ容量がわかります。また、一部のデータベースには、大きな(おそらく無制限の)テキストと小さな固定長テキストを格納する方法が異なる場合があります(データベースによって異なる場合があります。詳細については、マニュアルを参照してください)。

なぜdecimal、float、intなのですか?

さまざまなレベルの精度が必要とするストレージの量は異なり、すべての使用が最高の精度を必要とするわけではありません。たとえば、こちらを参照してください:https : //docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracleには、表現できる精度のレベルと数値のサイズの点で、異なるストレージ要件と異なる機能を備えた非常に多くの異なる数値型があります。


2

ある程度、それは歴史的です。

むかしむかし、表形式のデータは、固定長レコードで構成されるファイルに格納され、順番に定義済みフィールドで構成されていたため、特定のフィールドは常にすべてのレコードで同じタイプで同じ場所にありました。これにより、処理が効率的になり、コーディングの複雑さが制限されました。

このようなファイルにいくつかのインデックスを追加すると、リレーショナルデータベースの始まりがあります。

リレーショナルデータベースの進化に伴い、可変長テキストやバイナリフィールドなど、より多くのデータ型とストレージオプションが導入され始めました。しかし、これにより可変長レコードが導入され、計算によるレコードの一貫した検索、または固定オフセットによるフィールドの検索ができなくなりました。いずれにせよ、今日のマシンは当時よりはるかに強力です。

フィールドに特定のサイズを設定して、ビジネスロジック(北米の電話番号に10桁など)を適用するのに役立つ場合があります。多くの場合、それはほんの少しのコンピューティングレガシーです。


1

データベースが固定サイズのレコードを使用している場合、データベース内のすべてのレコードは、その内容が変更された場合でも同じ場所に収まり続けます。対照的に、データベースがフィールドに必要なストレージ容量を正確に使用してレコードを保存しようとすると、Emma Smithの名前をEmma Johnsonに変更すると、レコードが大きすぎて現在の場所に収まらない場合があります。十分なスペースがある場所にレコードを移動した場合、新しい場所を反映するために、レコードの場所を追跡するインデックスを更新する必要があります。

このような更新に関連するコストを削減するには、さまざまな方法があります。たとえば、システムがレコード番号とデータの場所のリストを保持している場合、レコードが移動した場合に更新する必要があるのはそのリストのみです。残念ながら、そのようなアプローチにはまだかなりのコストがかかります(たとえば、レコード番号と場所の間のマッピングを維持するには、レコードの取得に特定のレコード番号に関連付けられたデータを取得するための追加ステップが必要です)。固定サイズのレコードを使用するのは非効率に思えるかもしれませんが、物事がずっと簡単になります。


1

Web開発者としてあなたがしていることの多くについて、「内部で」何が起こっているのかを理解する必要はありません。ただし、役立つ場合もあります。

「この列のエントリにはプレーンテキストデータが256バイトしかありません」とデータベースに伝えることの利点は何ですか。または「この列には最大16,777,215バイトのテキストエントリを含めることができますか?」

あなたが疑うように、理由は効率に関係しています。抽象化リークSELECT author FROM booksテーブル内のすべてのフィールドのサイズがわかっている場合、次のようなクエリは非常に迅速に実行できます。

ジョエルが言うように、

リレーショナルデータベースはどのように実装されSELECT author FROM booksますか?リレーショナルデータベースでは、テーブル(例:booksテーブル)のすべての行はバイト単位でまったく同じ長さであり、すべてのフィールドは常に行の先頭から固定オフセットにあります。したがって、たとえば、booksテーブルの各レコードが100バイト長で、authorフィールドがオフセット23にある場合、バイト23、123、223、323などに保存されている著者がいます。移動するコードは何ですかこのクエリの結果の次のレコードは?基本的には、これです:

pointer += 100;

1つのCPU命令。すごい

多くの場合、気にする必要のない本質的な基盤から十分に離れて作業しています。PHPベースのWeb DEVとして、あなたが気にどのように多くのCPU命令あなたのコードの用途については?ほとんどの場合、いや、そうでもない。ただし、次の2つの理由から、知っておくと役立つ場合があります。ライブラリによって行われた決定を説明できること。時には、自分のコードの速度に注意する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.