私は現在SQLデータベースを使用していますが、これはいつも気になっていましたが、Googleの検索はそれほどうまくいきません。なぜ、厳密なデータ型なのですか。
バイナリデータとプレーンテキストデータの区別が重要である など、いくつかの異なるデータタイプがある理由を理解しています 。バイナリデータの1と0をプレーンテキストとして格納するのではなく、バイナリデータを独自の形式で格納する方が効率的であることがわかりました。
しかし、私が理解していることわからないとは、たくさん異なるデータ型:
mediumtext
、longtext
、text
なのですか?decimal
、float
、int
なのですか?データベースに「この列へのエントリには256バイトのプレーンテキストデータしかない」と伝えることの利点は何ですか。または「この列には、最大16,777,215バイトのテキストエントリを含めることができます」?
パフォーマンス上のメリットですか?その場合、エントリのサイズを事前に知っているとパフォーマンスが向上するのはなぜですか。それとも、それは完全に別の何かですか?
[〜#〜] sql [〜#〜] は、 静的に型指定された 言語です。つまり、変数(またはこの場合はフィールド)を使用する前に、その変数のタイプを知る必要があります。これは、動的型付け言語とは逆であり、必ずしもそうではありません。
そのコアでは、SQLはデータ( [〜#〜] ddl [〜#〜] )を定義し、データにアクセスするように設計されています( [〜#〜 ] dml [〜#〜] ) リレーショナルデータベース エンジン。このタイプのシステムでは、静的型付けには動的型付けよりもいくつかの利点があります。
特定のレコードにすばやくアクセスするために使用されるインデックス は、サイズが固定されている場合に非常にうまく機能します。複数のフィールドを持つ可能性のあるインデックスを使用するクエリを考えてみます。データタイプとサイズが事前にわかっている場合、述語(WHERE句またはJOIN条件)をインデックスの値と非常にすばやく比較して、目的のレコードをより早く見つけることができます。 。
2つの integer 値を考えます。動的型システムでは、サイズが可変である可能性があります(Java BigInteger
、またはPythonの組み込みの任意精度整数を考えてください)。整数を比較したい場合は、最初にそれらのビット長を知る必要があります。これは、現代の言語ではほとんど隠されている整数比較の側面ですが、CPUレベルでは非常に現実的です。サイズが固定されており、事前にわかっている場合は、ステップ全体が削除されます。繰り返しになりますが、データベースは何十億ものトランザクションを可能な限り迅速に処理できるはずです。
SQLは1970年代に設計されました。マイクロコンピューティングの初期の頃は、メモリが貴重でした。データを制限することで、ストレージ要件を抑えることができました。整数が1バイトを超えて大きくならない場合、なぜそれ以上のストレージを割り当てるのですか?これは、メモリが限られている時代の無駄なスペースです。現代でも、これらの余分な無駄なバイトは、CPUのキャッシュのパフォーマンスを増大させ、停止させる可能性があります。これらは、ごく小さな開発環境だけでなく、毎秒数百のトランザクションを処理するデータベースエンジンであることを忘れないでください。
限られたストレージの境界線に沿って、メモリ内の単一のページに単一のレコードを収めることができると便利です。 1ページを超えると、ページミスが多くなり、メモリアクセスが遅くなります。新しいエンジンには、これを問題の少ないものにするための最適化がありますが、それでもまだあります。データのサイズを適切に設定することで、このリスクを軽減できます。
さらに現代では、SQLは [〜#〜] orm [〜#〜] または [〜#〜を介して他の言語にプラグインするために使用されます] odbc [〜#〜] またはその他のレイヤー。これらの言語の一部には、強力な静的型の要求に関するルールがあります。動的に型付けされた言語は静的な型を他の方法よりも簡単に処理できるため、より厳密な要件に準拠することが最善です。
SQLは静的型付けをサポートしています。これは、上記のように、データベースエンジンがパフォーマンスのために静的型付けを必要とするためです。
not強く型付けされたSQLの実装があることに注意してください。 SQLite は、おそらくそのようなリレーショナルデータベースエンジンの最も一般的な例です。また、単一のシステムでシングルスレッドで使用するように設計されているため、パフォーマンスの問題は、たとえば、毎分数百万のリクエストを処理するエンタープライズOracleデータベース。
最初:プレーンテキストはバイナリです(UTF8でもASCII文字「0」と「1」でもありませんが、実際のオン/オフビット)
そうは言っても、理由のいくつかは次のとおりです。
これは、データベースが記述されている基本的なコードが固定サイズのレコードを割り当てて使用できるようにするためです。特定のフィールドに0〜256文字のテキストを含めることができる場合、256バイトのブロックを割り当てて格納できます。
これにより、物事がはるかに速くなります。特定のフィールドは常にレコードからxバイトを開始するため、ユーザータイプとして追加のストレージを割り当てる必要はありません。検索またはそのフィールドでの選択は、各レコードへのxバイトを常にチェックすることがわかっているためです。
データベースの列に定義された型が指定されている場合、型は通常、ビット単位で特定のサイズを持つように定義されます。結果として:
1)データベースエンジンがテーブルの行をトラバースする場合、各レコードがどこで終了するかを判別するために特別な解析を行う必要はありません。各行がたとえば32バイトで構成されていることを知ることができるため、次のレコードは、現在のレコードの場所に32バイトを追加するだけで十分です。
2)行内のフィールドを検索する場合、何も解析せずにそのフィールドの正確なオフセットを再度知ることができるため、列の検索は、コストがかかる可能性のあるデータ処理ではなく、単純な算術演算です。
なぜ DBMSには静的なデータ型があります。
ルックアップの速度。 DBMSの要点は、プログラムにロードできるよりもはるかに多くのデータを格納することです。 「過去10年間に世界中で発生したすべてのクレジットカードの伝票」を考えてみてください。このようなデータを効率的に検索するには、固定長データ型が役立ちます。これは、日付スタンプや口座番号などの構造化データに特に当てはまります。事前に何を処理しているかがわかっている場合は、効率的なインデックスにロードする方が簡単です。
整合性と制約。データ型が固定されていると、データをクリーンに保つことが容易になります。
歴史。 RDBMSは、コンピューターに数メガバイトのRAMしかなく、テラバイト規模のストレージが非常に高価なときに始まりました。テーブルの各行に数十バイトを保存すると、そのような状況で数千ドルと時間を節約できます。
顧客ベースの呪い。今日のRDBMSは非常に複雑で高度に最適化されたソフトウェアパッケージであり、データを蓄積して数十年にわたって使用されてきました。彼らは成熟しています。彼らが働きます。大規模なデータ損失を引き起こすRDBMSのクラッシュは、最近では非常にまれです。より柔軟なデータ型システムで何かに切り替えることは、ほとんどの組織にとってコストやリスクに見合う価値がありません。
類推:狭いレールゲージで都市の地下鉄システムがよりよく機能する(静かで、より速く、より電力効率が良い)ことは盲目的に明白かもしれません。しかし、これらの改善を実現するために、ニューヨーク市の地下鉄システムのRails)をどのように変更するのですか?そうではないので、自分が持っているものを最適化します。
一般に、データベースに保存内容を詳しく伝えるほど、そのデータに関連するさまざまなパフォーマンスメトリックを最適化しようとします。たとえば、ディスクに割り当てる容量や、ディスクを取得するときに割り当てるメモリ量などです。
なぜミディアムテキスト、ロングテキスト、テキストなのですか?
使用しているデータベースが不明なので、推測する必要があります:これらのデータ型の2つには上限があり、1つには上限がないと思います。上限のあるテキストにデータ型を使用すると、各レコードに必要なストレージ容量がデータベースに通知されます。また、一部のデータベースでは、大きな(場合によっては無制限の)テキストと小さな固定長のテキストを保存する方法が異なる場合があります(データベースによって異なる場合があります。マニュアルで確認してください)。
なぜdecimal、float、intなのですか?
精度のレベルが異なれば、必要となるストレージの量も異なります。また、使用するたびに最高の精度が要求されるわけではありません。たとえば、こちらをご覧ください https://docs.Oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF5095
Oracleには、表現できる数値の精度とサイズのレベルに関して、さまざまなストレージ要件とさまざまな機能を備えた非常に多くのさまざまな数値型があります。
ある程度、それは歴史的です。
むかしむかし、表形式のデータは、所定のフィールドが常に同じタイプであり、すべてのレコードの同じ場所にあるように、事前定義されたフィールドで構成される固定長レコードで構成されるファイルに保存されていました。これにより、処理が効率的になり、コーディングの複雑さが制限されました。
そのようなファイルにいくつかのインデックスを追加すると、リレーショナルデータベースの始まりです。
リレーショナルデータベースが進化するにつれて、可変長テキストやバイナリフィールドなど、より多くのデータタイプとストレージオプションが導入され始めました。しかし、これにより可変長レコードが導入され、計算または固定オフセットによるフィールドを介して一貫してレコードを特定する機能が中断されました。とにかく、今日のマシンは当時よりもはるかに強力です。
場合によっては、フィールドに特定のサイズを設定して、ビジネスロジックの一部を適用することが役立ちます。たとえば、北米の電話番号には10桁を使用します。ほとんどの場合、それはほんの少しのレガシーコンピューティングです。
あなたがウェブ開発者として何をしているのかについては、「内部」で何が起こっているのかを理解する必要はありません。ただし、役立つ場合があります。
データベースに「この列へのエントリには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命令。 Faaaaaaaaaast。
多くの場合、あなたはそれを気にする必要のない、骨の粗い土台から十分離れて作業しています。 PHPベースのWeb開発者として、コードが使用するCPU命令の数に気を配っていますか??ほとんどの場合、そうではありません。しかし、2つの理由から、知っておくと役立つ場合があります。ライブラリによって行われた決定を説明できる場合があります。また、独自のコードで速度を気にする必要がある場合もあります。
データベースが固定サイズのレコードを使用している場合、その内容が変更されても、データベース内のすべてのレコードは同じ場所に収まります。対照的に、データベースがフィールドに必要なストレージ容量を正確に使用してレコードを保存しようとする場合、Emma Smithの名前をEmma Johnsonに変更すると、レコードが大きすぎて現在の場所に収まらない場合があります。レコードが十分なスペースのある場所に移動された場合、新しい場所を反映するように、レコードがどこにあるかを追跡するインデックスを更新する必要があります。
このような更新に関連するコストを削減するには、さまざまな方法があります。たとえば、システムがレコード番号とデータの場所のリストを保持している場合、そのリストは、レコードが移動した場合に更新する必要がある唯一のものになります。残念ながら、そのようなアプローチには依然として大きなコストがかかります(たとえば、レコード番号と場所の間のマッピングを維持するには、レコードの取得で、特定のレコード番号に関連付けられたデータを取得するための追加の手順が必要になります)。固定サイズのレコードを使用すると効率が悪いように見えるかもしれませんが、これにより物事がずっと簡単になります。