web-dev-qa-db-ja.com

MySQL VARCHARサイズのパフォーマンスへの影響

MySQLのvarcharサイズ間にパフォーマンスの違いはありますか?たとえば、varchar(25)varchar(64000)などです。そうでない場合、部屋が不足しないように、最大​​サイズですべてのvarcharを宣言しない理由はありますか?

46
BenV

CHARとVARCHARのトレードオフを理解する必要があります

CHARフィールドでは、割り当てたものがまさに得られるものです。たとえば、CHAR(15)は、フィールドにどのように文字を配置しても、15バイトを割り当てて保存します。データフィールドのサイズは完全に予測可能であるため、文字列操作はシンプルで簡単です。

VARCHARフィールドを使用すると、完全に異なるストーリーが得られます。たとえば、VARCHAR(15)は、実際には最大16バイト、データには最大15バイト、そしてデータの長さを格納するために少なくとも1バイトを動的に割り当てます。保存する文字列 'hello'がある場合、5バイトではなく6バイトかかります。文字列操作では、常に何らかの形で長さチェックを実行する必要があります。

次の2つのことを行うと、トレードオフがより明確になります。
1。数百万または数十億の行を格納する
2。 CHARまたはVARCHARの列にインデックスを付ける

トレードオフ#1

可変長のデータでは行が小さくなり、物理ファイルも小さくなるため、VARCHARには明らかに利点があります。

トレードオフ#2

CHARフィールドはフィールド幅が固定されているため、必要な文字列操作が少ないため、CHARフィールドに対するインデックスルックアップは、VARCHARフィールドよりも平均20%高速です。これは私の推測ではありません。本 MySQLデータベースの設計とチューニング は、これを証明するためにMyISAMテーブルで素晴らしいことを行いました。本の例は次のようなことをしました:

ALTER TABLE tblname ROW_FORMAT=FIXED;

このディレクティブは、VARCHARがCHARとして動作することを強制します。私は前の仕事で2007年にこれを行い、300 GBのテーブルを取り、インデックスの検索を20%高速化しました。公開されたとおりに機能しました。ただし、テーブルのサイズはほぼ2倍になりますが、それは単にトレードオフ#1に戻ります。

格納されているデータを分析して、MySQLがカラム定義に推奨するものを確認できます。任意のテーブルに対して次のコマンドを実行するだけです。

SELECT * FROM tblname PROCEDURE ANALYSE();

これにより、テーブル全体が走査され、含まれるデータ、最小フィールド値、最大フィールド値などに基づいて、すべての列の列定義が推奨されます。場合によっては、CHARとVARCHARの計画で常識を使用する必要があります。ここに良い例があります:

IPアドレスを格納する場合、そのような列のマスクは最大15文字(xxx.xxx.xxx.xxx)です。 IPアドレスの長さはそれほど変化せず、追加のバイトによって制御される文字列操作の複雑さが増すため、ハートビートのCHAR(15)ですぐにジャンプします。このような列に対しても、PROCEDURE ANALYSE()を実行できます。 VARCHARを推奨することもあります。この場合、私のお金はまだVARCHARよりもCHARです。

CHARとVARCHARの問題を解決するには、適切な計画を立てる必要があります。大きな力には大きな責任が伴います(陳腐だが真実)

30
RolandoMySQLDBA

これに対する答えは実際にはかなり複雑です。ショートバージョン:違いがあります

  1. 結果をフィルターする一時テーブルを作成するとき(例:GROUP BYステートメント)、全長が割り当てられます。

  2. ワイヤープロトコル(行をクライアントに送信)は、おそらくより長い長さを割り当てます。

  3. ストレージエンジンは、適切なvarcharを実装する場合と実装しない場合があります。

(2)については、ワイヤプロトコルは私が精通しているものではないことを認めますが、ここでの一般的なアドバイスは、長さを推測するために少なくともいくつかの最小限の労力をかけることです。

13
Morgan Tocker

このスレッドの回答のほとんどは  InnoDBとutf8がデフォルトになる前に書かれた8歳。だから、最初からやり直してみましょう...

クエリで内部一時テーブルが必要な場合、MEMORYテーブルを使用しようとします。ただし、MEMORYは使用できません。

  • TEXTであっても、フェッチされるBLOB/TINYTEXT列。
  • VARCHARは、ある量よりも大きく、おそらく現在のバージョンでは512です。

また、VARCHARsCHARsに変換されることに注意してください。 (8.0はこれを変更します。)したがって、VARCHAR(255)に_CHARACTER SET utf8_を指定すると、列の内容に関係なく、765バイトに拡張されます。次に、これがトリガーされる可能性があります。

  • MEMORYテーブルが_max_heap_table_size_ or _tmp_table_size_のどちらよりも大きくなると、MyISAMに変換され、ディスクに流出する可能性があります。

したがって、VARCHAR(25)MEMORYのままである可​​能性が高く、そのため高速になります。 _(255)_はそれほど良くなく、_(64000)_は悪い。

(将来的には、一時テーブルはInnoDBになる可能性があり、この回答の一部を修正する必要があります。)

11
Rick James

このサイズのvarchar列により、テーブル全体に対するクエリで一時テーブルが使用される可能性が高くなります。 High Performance MySQLの本によると。オプティマイザがこのクエリをメモリ内で実行できるかどうか、または一時テーブルが必要かどうかを確認しようとすると、テーブル定義に基づいて行サイズを確認します。つまり、速度のために、64K文字の量は確認しません。実際に使用しています。これが、列に入力される実際の可能な値を超えて定義を拡張しないことをライターが推奨する理由です。明らかに、(実際のデータサイズがRAMに収まる場合でも)一時テーブルに入るクエリを増やすように設定すると、I/Oペナルティが発生しなくなりました。

6
TechieGurl

小さなフィールドは直接インデックスに含めることができますが、長いフィールドは直接含めることができないというのは私の理解です。その制限のために、文字列をインデックス可能にしたい場合は、短くしておくといいでしょう。それ以外の場合は、いいえ、どちらもvarcharであるため、並べ替えや比較などの操作は、フィールドが25であろうとMAXであろうと、同じような時間で動作します。

5
jcolebrand

部屋が不足しないようにしてください

このフレーズは、データベースに格納するデータがわからないため、質問することを意味します。それが本当である場合、容量計画のために必要になるため、できるだけ早く見つけることができます。たとえば、7000文字のデータ要素を取得する場合は、DBMSのパフォーマンスに影響を与えるため、知っておく必要があります。

とはいえ、予想されるコンテンツに関連する列サイズを使用することを好みます。たとえば、国番号と内線番号を含めても、電話番号が50文字を超えることはほとんどありません。同様に、郵便番号は20文字以下である可能性が高いです。

3
Larry Coleman