MySQLでvarcharサイズにパフォーマンスの違いはありますか?たとえば、varchar(25)
およびvarchar(64000)
。そうでない場合、スペースが不足しないようにするために、すべてのvarcharを最大サイズで宣言しない理由がありますか?
MySQLでvarcharサイズにパフォーマンスの違いはありますか?たとえば、varchar(25)
およびvarchar(64000)
。そうでない場合、スペースが不足しないようにするために、すべてのvarcharを最大サイズで宣言しない理由がありますか?
回答:
CHARとVARCHARを使用することのトレードオフを理解する必要があります
CHARフィールドを使用すると、割り当てたものが正確に得られます。たとえば、CHAR(15)は、フィールドにどのように文字を配置しても、15バイトを割り当てて保存します。データフィールドのサイズは完全に予測可能であるため、文字列の操作は簡単で簡単です。
VARCHARフィールドを使用すると、まったく異なるストーリーが得られます。たとえば、VARCHAR(15)は実際に最大16バイト、データ用に最大15バイト、データの長さを格納するために少なくとも1バイトを動的に割り当てます。文字列 'hello'を保存する場合、5ではなく6バイトを使用します。文字列操作では、常に何らかの形式の長さチェックを実行する必要があります。
:あなたは二つのことを行う際にはトレードオフがより明白である
。1.保存する何百万または数十億行
CHARまたはVARCHARのどちらかである。2.インデックス列を
可変長のデータでは行が小さくなり、物理ファイルが小さくなるため、明らかにVARCHARには利点があります。
CHARフィールドは固定されたフィールド幅のために文字列の操作が少ないため、CHARフィールドに対するインデックス検索は、VARCHARフィールドよりも平均20%高速です。これは私の側の推測ではありません。ブックMySQLデータベースの設計とチューニングがこれを証明するためにMyISAMテーブルの上に素晴らしい何かを行いました。本の例は次のようなことをしました。
ALTER TABLE tblname ROW_FORMAT=FIXED;
このディレクティブの強制は、CHARとして動作するVARCHARです。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の問題は、適切な計画を通してのみ解決できます。大きな力には大きな責任が伴います(決まり文句ですが真実)
これに対する答えは実際にはかなり複雑です。短いバージョン:違いがあります。
結果(GROUP BY
ステートメントなど)をフィルターする一時テーブルを作成する場合、完全な長さが割り当てられます。
ワイヤープロトコル(クライアントへの行の送信)は、おそらくより長い長さを割り当てます。
ストレージエンジンは、適切なvarcharを実装する場合としない場合があります。
(2)の場合、ワイヤープロトコルは親しみのあるものではないことを認めていますが、ここでの一般的なアドバイスは、長さを推測するために少なくとも最小限の労力をかけることです。
このスレッドの回答のほとんどは5年前のもので、InnoDBとutf8がデフォルトになる前に書かれました。それでは、最初からやり直します...
クエリが内部一時テーブルを必要とするとき、テーブルを使用しようとしMEMORY
ます。ただし、次の場合はMEMORYを使用できません。
TEXT
/ BLOB
でも取得されていない列TINYTEXT
。VARCHAR
現在のバージョンではおそらく512よりも大きいです。また、にVARCHARs
変わっていることに注意してくださいCHARs
。したがって、列の内容に関係なく、VARCHAR(255)
a CHARACTER SET utf8
は765バイトに拡張されます。次に、これがトリガーされる場合があります。
MEMORY
、テーブルがいずれよりも大きくなっmax_heap_table_size
たり tmp_table_size
、それはMyISAMテーブルに変換され、潜在的にディスクにスピルされます。ですから、VARCHAR(25)
にとどまる可能性が高いMEMORY
ため、高速になります。 (255)
あまり良くなくて(64000)
悪いです
(将来、一時テーブルはおそらくになりInnoDB
、この回答の一部は修正する必要があります。)
サイズが大きいvarchar列は、テーブル全体に対するクエリで一時テーブルを使用する可能性が高くなります。High Performance MySQLの本によると。オプティマイザーは、このクエリをメモリで実行できるか、一時テーブルが必要かどうかを確認しようとすると、テーブル定義に基づいて行サイズを調べます。つまり、速度のために、64K文字がどれだけあるかは調べません。実際に使用しています。そのため、作家は、列に表示される実際の可能な値を超えてその定義を広げないことを推奨しています。明らかに、一時テーブルに入るクエリを増やすように設定すると(実際のデータサイズがRAMに収まる場合でも)、回避できるI / Oペナルティが発生します。
小さいフィールドはインデックスに直接含めることができますが、長いフィールドはできません。その制限のため、文字列をインデックス可能にしたい場合は、短くすることをお勧めします。それ以外の場合、いいえ、両方がvarcharであるため、並べ替えや比較などの操作は、フィールドが25であろうとMAXであろうと同じように動作します。