MySQL:VARCHARとTEXTが大きいですか?


845

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

VARCHAR(3000)またはTEXTを使用する根拠はありますか?VARCHAR(3000)を記述するだけで、直感に反するようなものがあります。私はStack Overflowで他の同様の投稿をしましたが、このタイプの一般的なメッセージの格納に固有のビューを取得するのに適しています。


27
少し古いですが、これについて考えさせられる問題に出くわしたので、ここに来ました。私の場合、フロントエンドフォームは2,000文字に制限されていましたが、私の記憶方法で暗黙のエンコードは、国際文字を複数の文字としてエンコードしました(文字ごとに3〜12のどこかにあります)。だから私の2,000は突然24,000になりました。考えること...
ジェームズS

3
多くの同時挿入でテキストが大幅に高速になることがわかりました。
レイS. 14年

1
@JamesS:utf8mb4 ...>。<
分割

10
@RickJamesは、質問を閉じるのではなく、更新された回答を投稿することを検討します
Yvette

3
@YvetteColomb-回答を追加しました。Accepted Answerは古くなっているので、主に削除したいと思います。誰かが間違った情報を引用して「754賛成票なので、正しいに違いない」と言ってQ&Aに来ました。はい、承認済みの回答も編集しました。(それは不適切に感じられます。)
リック・ジェームズ

回答:


811
  • TEXTそして、実際のストレージの場所へのポインタを持っているテーブルで、テーブルの外に格納するBLOB ことができます。それが格納される場所は、データサイズ、列サイズ、row_format、MySQLバージョンなど、多くの要素に依存します。

  • VARCHARテーブルとインラインで格納されます。VARCHARサイズが妥当な場合は高速ですが、トレードオフはデータとハードウェアに依存するため、実際のシナリオをデータでベンチマークする必要があります。


148
+1:データが頻繁に取得される場合(ほとんどのクエリに含まれる)、VARCHAR(インラインで格納)は通常高速です。ただし、通常は取得されない(つまり、クエリで参照されない)大量のデータの場合は、データをインラインで保存しない方がよい場合があります。インラインで格納されるデータの場合、行サイズに上限があります。
spencer7593

21
@Pacerier:「インライン」ストレージを回避することの正確な利点は、ブロックに保存できる行数が増えることです。これは、テーブル行がInnoDBバッファーキャッシュで占めるブロックが少なくなる(メモリフットプリントが小さくなる)ことを意味します。ディスクとの間で転送されるブロック(I / Oの削減)。ただし、これは、「行外」に格納された列がクエリによってほとんど参照されない場合のパフォーマンス上の利点にすぎません。これらの「オフ・ロー」列がほとんどの照会で参照されている場合、その利点はほとんどなくなります。列が最大行サイズに収まり、頻繁に参照される場合は、インラインが推奨されます。
spencer7593 2013年

231
「サイズが妥当な場合、VARCHARの方が高速です」。「妥当な」文字数、100とは何ですか?1000?10万?
ティムピーターソン2013

125
この答えはInnoDBには正しくありません。特定の行の値がページサイズに収まる場合、VARCHARとBLOB / TEXTの両方が他の列とインラインで格納されます(16KBで、各ページには少なくとも2つの行を保持する必要があります)。文字列がそのために大きすぎる場合、追加のページにオーバーフローします。詳細については、mysqlperformanceblog.com / 2010/02/09 / blob-storage-in-innodbを参照してください。
Bill Karwin

14
私が正しく理解していた場合@BillKarwinは...その後の間には、性能差があってはならないvarcharblob/ text小さなテキスト項目のためのInnoDBの?では、すべてvarchartext型にして、DBにインラインとオーバーフローを管理させるのが賢明でしょうか。
ryvantage 2014年

474

ユーザー入力の長さを予測できますか?

VARCHAR(X)

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


テキスト

ケース:メッセージ、メール、コメント、書式付きテキスト、html、コード、画像、リンク


MEDIUMTEXT

ケース:大きなjson本文、短から中長の本、csv文字列


長いテキスト

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


7
予測可能性は本当にここでの副次的な項目です。決定的な要素となるのは、実際には最大予想長です。あなたがより予測可能であるとあなたが言及するアイテムは、それらが他のものより短いので、その方法だけです。
Andrew Barber

29
@ andrew-barberそれが私のポイントです。他のすべての投稿は違いについてよく説明していますが、実際に2つの中から選択する必要がある状況については説明していません。予想どおりに短い文字列にvarcharを使用することをお勧めします。任意に長い文字列を使用することをお勧めします。
マイケルJ.カルキンス

1
すべての列が短く予測可能である場合(例:MACアドレス、IMEIなどは決して変更されないものです)、CHAR列を使用して行サイズを固定することができます。これにより、MyISAMを使用している場合は、かなりスピードアップするはずです。また、私はそれについて確信がありませんが、InnoDb。
マット

1
@ MichaelJ.Calkins MySQL 5.6で起こったこと。これで、InnoDBで全文検索もできるようになりました。dev.mysql.com/doc/refman/5.6/en/fulltext-search.htmlを
PhoneixS

7
文字制限:TINYTEXT:255; テキスト:65,535; MEDIUMTEXT:16,777,215; LONGTEXT:4,294,967,29。
Victor Stoddard

218

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

  1. ほとんどの場合、テキスト形式のメッセージはTEXTとして保存する必要があります(最終的に任意の長さになります)

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

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

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


「それがなくなるまで素晴らしい」とはどういう意味ですか?「ではない」とはどういう意味ですか?
Pacerier

7
@Pacerier「そうではない」の例を示すために、ジェームズは約である可能性があります:たとえば、非常に最近までPMで140文字の制限があったTwitterを例にとります。彼らはそれが賢明ではないと判断し、その制限を完全に削除することを選択しました。彼らがそのことについて前もって考えていなかったとしたら(おそらく確かにそうだったと思います...)、上で概説したシナリオにぶつかったでしょう。
PaulSkinner、2015

9
私は新しいデータベースを作成しているだけです。小さなコメントボックスに2000文字を超える文字を入力できる人はいないと思います。Jamesがメモしているように、今夜はユーザーが2600文字の長さの非常に有効なコメント。varchar(2000)を使用して、それより長くなる可能性はないと考えていたため、間違っていました。そう、そうでなければそれは素晴らしいです。私たちの場合、それが現れるのにほんの数日しかかかりませんでした。以下のルール、マイケル・J・カルキンス、これから使うと思います。メッセージのテキスト、コメント。
Lizardx 2016

1
@Pacerier「これは、大きくなるまではすばらしい」。言い換えれば、それはほとんど常に機能し、素晴らしいです...それがそれほど大きくない例外的な状況を除いて。
限定的な贖罪

@Pacerierは別の興味深い例が選択した回答のコメントで言及されています、基本的に彼は2,000文字のフロントエンド制限がありましたが、実際に導入された文字は通常の文字よりも多くのバイトを使用するコードページにあり、彼のデータベースは最終的にスペースを必要としました24k文字の場合は、導入される文字の実際のバイトサイズを考慮する必要があったからです。
RaptorX 2016

32

免責事項:私はMySQLのエキスパートではありません...しかし、これは問題についての私の理解です。

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

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


38
行の長さの制限は65,535バイトです[ dev.mysql.com/doc/refman/5.0/en/column-count-limit.html ]。列がutf8エンコードされている場合、これは3000文字のvarchar列が最大9000バイトを占めることを意味します。
Jan Fabry

7
UTF-8文字は最大4バイトなので、12,000バイトを意味すると思います(ここで理解していないMySQLの事柄がない限り)。
raylu、2011

13
@raylu MySQLのUTF-8は、1文字あたり最大3バイトしかサポートしないという点で「偽のUTF-8」であるため、MySQLのUTF-8でBMPプレーンを超えてユニコード文字を直接格納する方法はありません。これはMySQL 5.5で修正されています。
パチェリエ

2
この主張はMyISAMにのみ有効であると思います。確実なソースは見つかりませんが、InnoDB TEXTもテーブルにインラインで格納されていると思います。
dotancohen 2013

2
@dotancohen私は、InnoDBを使用した可変長データの格納が異なる可能性があることを説明するソースをここで見つけました(外部または行内にインラインで格納できます)mysqlserverteam.com/externally-stored-fields-in-innodb
KiX Ortillan

30

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

長い答え:

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

の制限が小さい場合、VARCHARに比べていくつかの利点がありTEXTます。

  • 「小さい」とは、バージョン、コンテキストなどに応じて、191、255、512、767、または3072などを意味しますCHARACTER SET
  • INDEXes列にインデックスを付けることができる大きさには制限があります。(767または3072 バイト。これはバージョンと設定に依存します)
  • 複合によって作成された中間テーブル SELECTs MEMORY(高速)またはMyISAM(低速)の2つの異なる方法で処理されます。「大きな」カラムが含まれる場合、遅い方の手法が自動的に選択されます。(バージョン8.0で大幅な変更が行われるため、この箇条書き項目は変更される可能性があります。)
  • 前の項目に関連して、TEXT(とは対照的にVARCHAR)すべてのデータ型はMyISAMに直接ジャンプします。つまりTINYTEXT、生成された一時テーブルのほうが、同等のものよりも自動的に低下しVARCHARます。(しかし、これは議論を第三の方向に導きます!)
  • VARBINARYのようなものVARCHARです。BLOBのようTEXTです。

他の回答への反論

元の質問では、1つのこと(どのデータ型を使用するか)が尋ねられました。受け入れられた回答は他の何かに答えました(オフレコストレージ)。その答えは古くなっています。

このスレッドが開始され応答されたとき、InnoDBには2つの「行フォーマット」しかありませんでした。その後すぐに、さらに2つの形式(DYNAMICおよびCOMPRESSED)が導入されました。

の保存場所はTEXTデータ型の名前ではなく、サイズVARCHAR()基づいています。以下のために更新され、大きなテキスト/ BLOBカラムのオン/オフレコードストレージの議論を参照してくださいこれを


1
ここにいくつかの良い洞察があります。これは受け入れられる答えになるはずです。
Kosta Kontos

2
@KostaKontos-賞賛と誤植の修正をありがとう。より良い答えが必要な場合は、8年と800回の賛成投票が遅すぎても、回答を追加します。
リックジェームス

7

上記の答えは主な問題を十分に主張していません:次のような非常に単純なクエリでも

(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バイトが使用されます。このような一時テーブルはメモリ内で処理できず、ディスクに書き込まれます。影響は壊滅的なものになると予想できます。

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


3
InnoDB:同じことがバージョン5.7まで適用されます。8.0では、varchar tempsは可変長です。
リックジェームズ

3

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

VARCHARを検索するよりも速く検索、更新、または削除するためにフィールドにインデックスを付ける必要がある場合は、どんなに大きくてもかまいません。これら2つのデータ型は性質が異なるため、VARCHAR(10000000)がTEXTフィールドと同じになることはありません。

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

TEXTに行くより。


部分的に誤解を招く情報:TEXT列全体をインデックス化することはできません。インデックスにTEXT列を含める場合は、長さを指定する必要があります。また、VARCHARは、VARCHARが255を超える場合、インデックスサイズに最大長があるため、全体をインデックス化することはできません。
eRadical

2

Varcharはメールアドレスなどの小さなデータ用で、Textはニュース記事などのはるかに大きなデータ用、Blobは画像などのバイナリデータ用です。

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

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

Blobははるかに遅いので、10000レコードのコストがかかる10000画像などのデータが少ない場合にのみ使用してください。

速度とパフォーマンスを最大化するには、以下のヒントに従ってください。

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

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

  3. 異なるテーブルの別々のテキスト

  4. 電話番号などのIDで左結合クエリを使用する

  5. Blobを使用する場合は、テキストと同じヒントを適用します

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

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