web-dev-qa-db-ja.com

MySQLテーブルのvarchar長の重要性

行が動的に挿入されるMySQLテーブルがあります。文字列の長さがわからないため、切り捨てたくないので、一般的に必要以上に大きいvarchar(200)にします。 varcharフィールドの長さを必要以上に大きくすると、パフォーマンスが大幅に低下しますか?

104
Brian

いいえ、その列に格納している値が常に(たとえば)50文字未満である場合、列をvarchar(50)またはvarchar(200)として宣言すると同じパフォーマンスが得られます。

58
Alex Martelli

パフォーマンスに影響する可能性が1つあります。MySQLでは、一時テーブルとMEMORYテーブルはVARCHARカラムを固定長カラムとして格納し、最大長までパディングされます。必要な最大サイズよりもはるかに大きいVARCHAR列を設計すると、必要以上のメモリを消費します。これは、キャッシュの効率、ソート速度などに影響します。

280
Bill Karwin

VARCHARは、「可変文字」の略であるため、説明する状況に最適です。例に基づいた制限は200文字ですが、それより少ないものはすべて受け入れられますand割り当てられた列のサイズを埋めません。

VARCHARもスペースを取りません-値は1バイトまたは2バイトの長さのプレフィックスとデータとして保存されます。長さのプレフィックスは、値のバイト数を示します。値が255バイトを超える必要がない場合、列は1バイトを使用し、値が255バイトを超える場合は2バイトを使用します。

MySQL CHARデータ型とVARCHARデータ型の比較の詳細については、 このリンク を参照してください。

14
OMG Ponies

サイズは性能です!サイズが小さいほど優れています。今日や明日ではなく、いつの日か、レイアウトのデザインに関係なく、深刻なボトルネックになるとテーブルが大きくなります。ただし、最初に発生する可能性がある設計フェーズの潜在的なボトルネックの一部を予測し、サーバーを追加してスキームを再検討したり、水平方向に拡張する必要があるまで、dbが高速かつ楽しく実行される時間を延長しようとします。

あなたのケースでは、多くのパフォーマンスリークが発生する可能性があります。長いvarchar列では大きな結合はほとんど不可能です。これらの列のインデックス作成は非常に効果的です。ディスクにデータを保存する必要があります。 1つのメモリページで保持できる行が少なくなり、テーブルスキャンの速度が大幅に低下します。また、クエリキャッシュがここで役立つことはほとんどありません。

自問する必要があります。年間何件の挿入が発生する可能性がありますか?平均長は?本当に200文字以上必要なのでしょうか、それともアプリケーションのフロントエンドで、ユーザーに最大長を通知しても、それをキャッチできますか?インデックス作成とスキャンを高速化するためにテーブルを狭いものに分割し、サイズが拡大する頻度の低い追加データを保持するために別のテーブルに分割できますか可能性のあるvarcharデータをカテゴリに入力し、いくつかのデータをいくつかの小さなint型またはbool型の列に抽出し、そのようにvarchar列を絞り込めますか?

ここで多くのことができます。最初の仮定を行ってから、実際の測定パフォーマンスデータを使用して段階的に再設計するのが最善の場合があります。がんばろう。

13
Nudge

パフォーマンス?いいえ。ディスクストレージですか?はい、しかし安価で豊富です。データベースがテラバイト規模に成長しない限り、おそらく大丈夫です。

4
duffymo

一部の人は、varchar(200)varchar(20)よりもディスク上のテーブルサイズを多く使用していると誤解しています。これはそうではありません。 255文字を超える場合にのみ、mysqlはvarcharフィールドデータの長さを決定するために余分なバイトを使用します。

4
DCH

パフォーマンスが低下する可能性がありますが、通常、ほとんどのユーザーが気付くレベルではありません。

各フィールドのサイズが事前にわかっている場合、MySQLは各フィールド/行の間にあるバイト数を正確に認識し、すべてのデータを読み取らずにページ送りできます。可変文字を使用すると、最適化のためのこの機能が低下します。

varcharはデータの断片化によりパフォーマンスが低下しますか?

さらに良いことに、 char vs varchar

ほとんどの用途では、どちらでも構いません-ただし、is違いがあり、大規模なデータベースでは、選択する理由がありますどちらか一方。

1
Rizwan Kassim

ほとんどのシナリオでchar列と同じようにvarchar列を表示し、長さを控えめに設定してください。 var修飾子を、最大長に関する意思決定に影響を与えるものとして常に考える必要はありません。実際には、提供される文字列の長さがさまざまであるという代わりに、パフォーマンスのヒントと見なす必要があります。

これは、データベース内部を厳密に従う必要があるディレクティブではなく、完全に無視できます。ただし、理想的な世界ではない場合でも、実装でリークが発生する場合があるため(固定長やパディングなど)、これには注意してください。

Varchar(255)を使用している場合、すべての状況でchar(255)とは異なるパフォーマンスを常に行うという保証はありません。

ストレージ要件に関するマニュアルに記載されているアドバイスに従って、255、65535などのような値に簡単に設定できます。これは、0(はい、それは問題です)から255までの値が同じ影響を持つという印象を与えます。しかし、それは完全に保証できるものではありません。

ストレージ要件は、行ストレージの点でまともで成熟した永続的なストレージエンジンにとって正しいか、適切な指標になる傾向があります。インデックスなどの指標としてはそれほど強力ではありません。

それは時々難しい質問であり、文字列の長さは正確にどれくらいの長さでなければならないのか、それはあなたが知っているはずの最高の範囲に設定しますが、影響はありません。残念ながら、これは多くの場合、ユーザーが解決するために残されたものであり、実際には多少arbitrary意的です。文字列のサイズを決して大きくしないとは言えません。これは、正確に判断できない場合があるためです。

少なくとも文字列が切り捨てられるのではなく、文字列が長すぎる場合は、MySQLクエリがエラーをスローするようにする必要があります。これにより、少なくともエラーの放出から短すぎるかどうかを確認できます。列を拡大または縮小するために列のサイズを変更すると、費用のかかるDDL操作になる可能性がありますので、注意してください。

長さとパフォーマンスが関係する場合、文字セットも考慮する必要があります。長さはバイトではなくこれを参照します。たとえば、MB4ではなくutf8を使用する場合、varchar(255)は実際にはvarbinary(3 * 255)です。テストを実行し、ソースコード/ドキュメントを詳しく調べることなく、このようなことが実際にどのように機能するかを知ることは困難です。このため、予想以上に大きな影響を与える過度の長さの余地があります。これはパフォーマンスだけに適用されるわけではありません。ある日、varcharカラムの文字セットをより大きなものに変更する必要がある場合、回避できたはずの長い文字列を無償で許可すると、頼りにならないで限界に達する可能性があります。これは通常かなりニッチな問題ですが、実際に発生します。これは最近、キー長に制限のあるMySQLおよびインデックス用のutf8mb4の導入に関する重大な問題でした。

MAX(LENGTH(column))が常に64未満であることが判明した場合(列定義と一致しない入力に制限があると判断された場合など)、varchar(255)がある場合は、一部のシナリオで必要なスペースの4倍のスペースを使用する可能性が高くなります。

これには以下が含まれます。

  • 異なるエンジン、いくつかはそれを完全に無視するかもしれません。
  • 更新や挿入などのバッファサイズは、255個すべてを割り当てる必要がある場合があります(これを証明するためにソースコードを確認していませんが、これは単なる仮説です)。
  • インデックス。これは、多くのvarchar(255)列から複合キーを作成しようとするとすぐに明らかになります。
  • 中間テーブルと場合によっては結果セット。トランザクションの動作方法を考えると、定義された制限ではなく、列の文字列の実際の最大長を使用することが常に可能であるとは限りません。
  • 内部予測最適化では、入力として最大長が必要になる場合があります。
  • データベース実装バージョンの変更。

経験則として、パフォーマンスの問題かどうかに関係なく、varcharを必要以上に長くする必要はまったくないので、できる限りそれを使用することをお勧めします。データのサイズのサンプリング、真の制限の実施、または質問/研究による真の制限の発見により多くの労力をかけることが理想的なアプローチです。

できない場合、疑問がある場合にvarchar(255)などの処理を行いたい場合は、科学を行うことをお勧めします。これは、テーブルを複製し、var char列のサイズを小さくしてから元のデータをそこにコピーし、インデックス/行データのサイズを確認することで構成されます(列にもインデックスを付け、プライマリキーとして試してください) InnoDBでは、行が主キーで順序付けられるため、動作が異なる場合があります)。少なくともこの方法では、最も敏感なボトルネックの1つであるIOに影響があるかどうかを知ることができます。メモリ使用量のテストはより難しく、テストするのは困難です。潜在的な最悪のケースをテストすることをお勧めします(メモリに多くの中間結果が含まれるクエリ、大きな一時テーブルのExplainを確認するなど)。

テーブルに行が多くないことがわかっている場合は、結合、インデックス(特に複合、一意)などに列を使用しないので、多くの問題は発生しません。

0
jgmjgm

単なるcharではなくvarcharであるため、サイズは内部フィールドに基づいて実際の長さと文字列自体を示します。そのため、varchar(200)を使用してもvarchar(150)を使用した場合とそれほど違いはありませんが、より多くのデータを保存できる可能性があります。

また、行が大きくなったときに更新で何が起こるかを考慮する必要があります。しかし、これがまれな場合は、問題ないはずです。

0
Rob Farley

言及できるもう1つの点は、可変長よりも固定長の行を使用する方が良いということです。たとえば、bigintよりも、char(n)datevarcharなどの列を使用することをお勧めします。行のサイズが固定されている場合、MySQLのMyISAMストレージエンジンの最高のパフォーマンスが達成されます。

0
Andronicus

データ型名が示唆するように、これはVARCHAR(つまり可変文字データストレージ)であるため、mysqlエンジン自体は保存されたデータに従って使用中のメモリを割り当てるため、私の知る限りパフォーマンスに影響はありません。

0
user2903114