回答:
いいえ、その列に格納している値が常に(たとえば)50文字未満の場合、その列をと宣言するvarchar(50)
かvarchar(200)
、同じパフォーマンスを発揮するという意味です。
パフォーマンスへの影響が1つ考えられます。MySQLでは、一時テーブルとMEMORY
テーブルはVARCHAR
列を固定長の列として格納し、最大長までパディングされます。VARCHAR
必要な最大サイズよりもはるかに大きい列を設計すると、必要以上のメモリが消費されます。これは、キャッシュ効率、ソート速度などに影響します。
MEMORY
テーブルが大きすぎると見なされると、ディスクに書き込まれ、パフォーマンスが大幅に低下します。
VARCHARは、あなたが記述の状況に最適です、それは「変数の文字」を意味するので-リミット、あなたの例に基づいて、200文字以内何でもだろうあまり受け入れられていると、列の割り当てられたサイズを記入しないであろう。
VARCHARはスペースも少なくて済みます-値は1バイトまたは2バイトの長さのプレフィックスとデータとして格納されます。長さプレフィックスは、値のバイト数を示します。値に255バイト以下が必要な場合、列は1つの長さバイトを使用し、値に255バイト以上が必要な場合、2つの長さバイトを使用します。
サイズは性能です!サイズが小さいほど良いです。今日や明日ではありませんが、設計がどのようなものであっても、深刻なボトルネックになると、いつかテーブルが大きくなることがあります。ただし、最初に発生する可能性が高い設計フェーズでの潜在的なボトルネックの一部を予測し、サーバーを追加してスキームを再考するか、水平方向にスケーリングする必要があるまで、dbが高速かつ幸福に実行される時間を拡大しようとすることができます。
あなたの場合、遭遇する可能性のある多くのパフォーマンスリークがあります:大きな結合は長いvarchar
列ではほとんど不可能です。それらの列のインデックス作成は本当にキラーです。ディスクにはデータを保存する必要があります。1つのメモリページはより少ない行を保持でき、テーブルスキャンははるかに遅くなります。また、クエリキャッシュはここでは役に立ちません。
あなたは自分自身に問いかける必要があります:年間何回の挿入が発生するのでしょうか?平均の長さは?最大長をユーザーに通知しても、実際に200文字以上必要ですか、それともアプリケーションのフロントエンドでそれをキャッチできますか?インデックス作成とスキャンを高速化するためにテーブルを狭いテーブルに分割し、拡張サイズのそれほど頻繁に必要とされない追加のデータを保持するために別のテーブルに分割できますか?可能なvarcharデータをカテゴリに入力して、一部のデータをいくつかの小さな、おそらくintまたはboolタイプの列に抽出し、そのようにvarchar列を絞り込めますか?
ここでたくさんすることができます。最初の仮定で行って、実際の測定されたパフォーマンスデータを使用して段階的に再設計するのが最善の場合があります。幸運を。
パフォーマンス?いいえ、ディスクストレージですか。はい、しかしそれは安くて豊富です。データベースがテラバイト規模に成長しない限り、おそらく大丈夫です。
一部のユーザーはvarchar(200)
、ディスク上のテーブルサイズがのテーブルサイズよりも大きいと誤解していますvarchar(20)
。これはそうではありません。mysqlが255文字を超えた場合にのみ、mysqlは追加のバイトを使用してvarchar
フィールドデータの長さを決定します。
MEMORY
テーブルではそうではありません。
パフォーマンスに影響が出る可能性がありますが、通常、ほとんどのユーザーが気付くレベルではありません。
各フィールドのサイズが事前にわかっている場合、MySQLは各フィールド/行の間にあるバイト数を正確に認識し、すべてのデータを読み取らずにページを転送できます。可変文字を使用すると、この最適化機能が低下します。
varcharはデータの断片化が原因でパフォーマンスに影響しますか?
さらに良いのは、charとvarcharです。
ほとんどの用途ではどちらでもかまいませんが、違いがあり、大規模なデータベースではどちらか一方を選択する理由があります。
データ型名からわかるように、これはVARCHAR、つまり可変文字データストレージです。mysqlエンジン自体が、格納されているデータに従って使用中のメモリを割り当てるため、私の知る限りパフォーマンスに影響はありません。
ほとんどのシナリオでchar列と同じようにvarchar列を表示し、長さを控えめに設定する必要があります。var修飾子を、最大長の決定に影響を与えるものと常に考える必要はありません。提供される文字列の長さがさまざまであることは、実際にはパフォーマンスのヒントと見なすべきです。
これは、データベース内部が厳密に続く必要があるディレクティブではなく、完全に無視できます。ただし、理想的な世界ではないはずの実装がリークする可能性があるため(固定長やパディングなど)、これには注意してください。
varchar(255)を使用している場合、すべての状況において、パフォーマンスの点で常にchar(255)とは異なる動作をするという保証はありません。
ストレージ要件についてのマニュアルのアドバイスに従って、255、65535などにインラインで設定するのは簡単に思えるかもしれません。これは、0(はい、事柄です)と255の間の任意の値が同じ影響を与えるという印象を与えます。ただし、これは完全に保証できるものではありません。
ストレージ要件は、行ストレージの観点から、まともな、または成熟した永続ストレージエンジンの適切な指標となる傾向があります。インデックスなどの指標としてはそれほど強力ではありません。
これは難しい質問になる場合があります。文字列がどれくらいの長さである必要があるかを正確に設定します。そのため、文字列が含まれるはずの上限に設定すると、影響はありません。残念ながら、これは多くの場合、解決するためにユーザーに残されたものであり、実際にはいくぶん恣意的です。正確にわからない場合もあるので、実際には文字列のサイズを大きくしないとは言えません。
文字列が切り捨てられるのではなく長すぎる場合、MySQLクエリがエラーをスローするようにして、少なくともエラーエミッションから文字列が短すぎるかどうかを確認する必要があります。列を拡大または縮小するために列のサイズを変更すると、費用のかかるDDL操作になる可能性があります。これは覚えておく必要があります。
文字セットは、長さとパフォーマンスが関係する場所でも考慮する必要があります。長さはバイトではなくこれを参照します。たとえばMB4ではなくutf8を使用している場合、varchar(255)は実際にはvarbinary(3 * 255)です。テストを実行したり、ソースコードやドキュメントを深く調べたりしないと、このようなことが実際にどのように行われるかを知ることは困難です。このため、予想外に膨らんだ影響を与える過度な長さの余地があります。これはパフォーマンスだけに当てはまるわけではありません。ある日、varcharカラムの文字セットをより大きな文字セットに変更する必要がある場合、無理に長い文字列を存在させて回避できたとしたら、頼りなく制限に達する可能性があります。これは通常、かなりニッチな問題ですが、実際に発生します。
MAX(LENGTH(column))が常に<64であることが判明した場合(たとえば、列の定義と一致しない入力に制限があると判断された場合)、varchar(255)がある場合、一部のシナリオで必要なスペースの4倍のスペースを使用する可能性が高いです。
これには以下が含まれます。
経験則として、とにかくvarcharを必要以上に長くする必要はありません。パフォーマンスの問題かどうかに関係なく、可能であればそれを守ることをお勧めします。データのサイズをサンプリングし、真の制限を適用するか、質問/調査を通じて真の制限を見つけるためにより多くの努力を払うことが理想的なアプローチです。
できない場合は、疑わしい場合にvarchar(255)などを実行したい場合は、科学を実行することをお勧めします。これは、テーブルを複製し、var char列のサイズを小さくしてから、データを元のテーブルからコピーして、インデックス/行データのサイズを調べることで構成される場合があります(列にもインデックスを付け、主キーとしても試してください)。行が主キーによって順序付けられるため、InnoDBでは動作が異なる場合があります)。少なくともこの方法で、最も敏感なボトルネックの1つになりがちなIOに影響があるかどうかがわかります。メモリ使用量のテストはより難しく、徹底的にテストすることは困難です。潜在的な最悪のケースをテストすることをお勧めします(メモリ内の中間結果が多いクエリ、大きな一時テーブルの説明で確認するなど)。
テーブルに多くの行がないことがわかっている場合は、その列を結合、インデックス(特に複合、一意)などに使用しないので、多くの問題は発生しません。
VARCHAR(255) utf8mb4
約15万行のインデックス付き列が1つあるテーブルのサイズは11.5MBです。VARCHAR(48) utf8mb4
同じデータ(最大長46文字)のインデックス付き列を持つテーブルは、4.5MBを使用しました。クエリにはそれほど大きな違いはありません。インデックスが付けられています。しかし、クエリのI / Oやデータベースのバックアップのようなもので追加されます。