web-dev-qa-db-ja.com

MySQL:大規模なVARCHARとTEXTの関係

ユーザー間のメッセージを記録するMySQLのメッセージテーブルを持っています。典型的なIDとメッセージタイプ(すべて整数タイプ)は別として、私は実際のメッセージテキストをVARCHARかTEXTのどちらかとして保存する必要があります。フロントエンドの制限を3000文字に設定しました。これは、メッセージがこれよりも長くdbに挿入されないことを意味します。

VARCHAR(3000)とTEXTのどちらを使ってもよいという根拠はありますか? VARCHAR(3000)を書くだけでは直感に反すると感じることがあります。私はStack Overflowに関する他の似たような投稿をしてきましたが、この種の一般的なメッセージ保存に特有の見解を得るのは良いでしょう。

801
Tom
  • TEXTBLOBは、実際のストレージの場所へのポインターを持つだけのテーブルで、テーブルから格納されます。

  • VARCHARはテーブルとインラインで格納されます。サイズが妥当であればVARCHARは速くなりますが、そのトレードオフはあなたのデータとあなたのハードウェアによりますので、あなたはあなたのデータで現実世界のシナリオをベンチマークしたいでしょう。

更新 VARCHARまたはTEXTがインラインで格納されるか、レコード外で格納されるかは、データサイズ、列サイズ、row_format、およびMySQLのバージョンによって異なります。 notは "text"と "varchar"のどちらに依存しますか。

786
MindStalker

ユーザー入力がどれくらいかかるか予測できますか?

VARCHAR(X)

ケース: ユーザー名、Eメール、国、件名、パスワード


テキスト

ケース: メッセージ、Eメール、コメント、フォーマットされたテキスト、HTML、コード、画像、リンク


MEDIUMTEXT

ケース: 大きいjson本体、短から中程度の長さの本、csv文字列


長いテキスト

事例: 教科書、プログラム、長年のログファイル、ハリーポッターと炎のゴブレット、科学研究記録

444

ベストプラクティスを明確にするためだけに:

  1. テキストフォーマットのメッセージはほとんどの場合TEXTとして格納されるべきです(それらは任意に長いものになってしまいます)

  2. 文字列属性はVARCHAR(保存先ユーザー名、件名など)として格納する必要があります。

私はあなたがフロントエンドの制限を持っていることを理解しています、それはそうでないまで素晴らしいです。 * grin *トリックは、DBをそれに接続するアプリケーションとは別のものとして考えることです。 1つのアプリケーションがデータに制限を課しているからといって、データが本質的に制限されているわけではありません。

メッセージ自体が3000文字を超えないようにするのは、メッセージ自体とは何ですか?それが単なる任意のアプリケーション制約(たとえばテキストボックスなど)の場合は、データ層にTEXTフィールドを使用します。

215
James

免責事項:私はMySQLの専門家ではありません...しかし、これは私が問題を理解していることです。

TEXTはmysqlの行の外側に格納されていると思いますが、VARCHARは行の一部として格納されていると思います。 mysql行には最大行長があります。そのため、VARCHARを使用して、1行に格納できる他のデータ量を制限できます。

また、VARCHARが行の一部を形成しているため、そのフィールドを検索するクエリはTEXTチャンクを使用するクエリよりもわずかに高速になると思われます。

32

簡単な答え: 実用的、パフォーマンス、またはストレージの違いはありません。

長い答え:

(MySQLでは)VARCHAR(3000)(またはその他の大きな制限)とTEXTの間に本質的な違いはありません。前者は3000 文字で切り捨てられます。後者は65535 バイトで切り捨てられます。 (私はbytescharactersを区別しています。なぜなら、文字は複数バイトをとることがあるからです。)

VARCHARの制限が小さい場合、TEXTよりも優れた点がいくつかあります。

  • 「より小さい」とは、バージョン、コンテキスト、およびCHARACTER SETに応じて、191、255、512、767、または3072などを意味します。
  • INDEXesはカラムのインデックス可能な大きさに制限があります。 (767または3072 バイト;これはバージョンと設定によって異なります)
  • 複雑なSELECTsによって作成された中間テーブルは、MEMORY(速い)またはMyISAM(遅い)という2つの異なる方法で処理されます。 「大きな」列が含まれる場合は、遅い方の手法が自動的に選択されます。 (バージョン8.0で大幅な変更が加えられたため、この箇条書き項目は変更されることがあります。)
  • 前の項目に関連して、(TEXTではなく)すべてのVARCHARデータ型は、MyISAMに直接ジャンプします。つまり、生成された一時テーブルの場合、TINYTEXTは同等のVARCHARよりも自動的に悪化します。 (しかし、これは3番目の方向への議論を取ります!)
  • VARBINARYVARCHARと同じです。 BLOBTEXTと同じです。

他の答えに反論する

最初の質問では、1つのこと(どのデータ型を使用するか)が尋ねられました。受け入れられた答えは他の何かに答えた(記録外の保存)。その答えは今時代遅れです。

このスレッドが開始されたときにandが応答したとき、InnoDBには2つの "行フォーマット"しかありませんでした。その後まもなく、さらに2つのフォーマット(DYNAMICCOMPRESSES)が導入されました。

TEXTおよびVARCHAR()の格納場所は、データ型名ではなくsizeに基づいています。 updated の大きなtext/blobカラムのon/offレコードの保存については、 this を参照してください。

20
Rick James

上記の答えは、主な問題を十分に主張しているわけではありません。

(SELECT t2.* FROM t1, t2 WHERE t2.id = t1.id ORDER BY t1.id) 

一時テーブルが必要な場合があります。また、VARCHARフィールドが含まれる場合は、一時テーブル内のCHARフィールドに変換されます。テーブルにVARCHAR(65000)フィールドを持つ500 000行と言う場合、この列だけで 6.5 * 5 * 10 ^ 9 byteが使用されます。このような一時テーブルはメモリ内で処理できず、ディスクに書き込まれます。その影響は壊滅的なものになると予想されます。

ソース(メトリック付き): https://nicj.net/mysql-text-vs-varchar-performance/ (これは、 "標準"(?)MyISAMストレージエンジンでのTEXTVARCHARの処理を指します。 InnoDBのように、他のものとは異なる場合があります。)

5
Max

VARCHARとTEXTにはHUGEの違いがあります。 VARCHARフィールドにはインデックスを付けることができますが、TEXTフィールドにはできません。 VARCHAR型フィールドはインラインで保存され、TEXTはオフラインで保存されます。実際には、TEXTデータへのポインターのみがレコードに保存されます。

VARCHARを使用するよりも高速に検索、更新、または削除するためにフィールドのインデックスを作成する必要がある場合は、サイズに関係ありません。これら2つのデータ型は性質が異なるため、VARCHAR(10000000)がTEXTフィールドと同じになることはありません。

  • アーカイブにのみフィールドを使用する場合
  • データ速度の取得を気にしない
  • 速度が重要ですが、検索クエリで演算子 '%LIKE%'を使用するため、インデックス付けはあまり役に立ちません
  • データ長の制限を予測することはできません

tEXTに行くよりも。

0
Viktor Joras

Varcharは電子メールアドレスのような小さなデータ用で、Textはニュース記事のようなもっと大きなデータ用です。Blobは画像などのバイナリデータ用です。

Varcharのパフォーマンスは、メモリから完全に実行されるため、より強力ですが、データがvarchar(4000)のように大きすぎる場合は、そうではありません。

一方、テキストはメモリに固執せず、ディスクのパフォーマンスの影響を受けますが、テキストデータを別のテーブルで区切って左結合クエリを適用してテキストデータを取得することでこれを回避できます。

Blobははるかに遅いので、10000レコードのような10000イメージのようなデータがあまりない場合にのみ使用してください。

最高のスピードとパフォーマンスを得るには、次のヒントに従ってください。

  1. 名前、タイトル、Eメールにはvarcharを使用

  2. 大きなデータにテキストを使用

  3. 別の表にテキストを区切る

  4. 電話番号などのIDでLeft Joinクエリを使用する

  5. Blobを使うつもりならば、Textと同じコツを当てはめてください。

これにより、データのサイズが10 Mを超え、サイズが最大10 GBまで保証されているテーブルでは、クエリに数ミリ秒かかることになります。

0
Creative87