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


45

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


3
+1この質問は、すべてのDBMSに同様に適用されます。私の観察では、多くのvarcharサイズが大きくなる傾向があります。
bernd_k

5
MySQLではありませんが、Depeszによるこのブログ投稿はPostgreSQLに関するあなたの質問に答えるかもしれません。
xenoterracide

回答:


29

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

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

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

:あなたは二つのことを行う際にはトレードオフがより明白である
。1.保存する何百万または数十億行
CHARまたはVARCHARのどちらかである。2.インデックス列を

トレードオフ#1

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

トレードオフ#2

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の問題は、適切な計画を通してのみ解決できます。大きな力には大きな責任が伴います(決まり文句ですが真実)


4
IPアドレスを保存する場合、int以外として保存する理由はありません。IPアドレスだけです。多くの言語には、ある種のip2int関数があります。:あなたは、コマンドライン呼び出しのconvienenceをしたい場合には、ABCDを変換するために、ストアドプロシージャ作ることは難しいことではありませんPOW(256,3)+ Bの POW(256,2)+ C * 256 + D
atxdba

1
ERRより多くの私はMySQLは、それが自分のip2int機能のしていると思うポイントに:INET_ATON
atxdba

3
@atxdba:私の答えのポイントは、単にCHAR対VARCHARを使用することです。文字列の文字サイズが15に近いため、IPを例として使用します。したがって、VARCHARを優先して安定したCHARサイズを四捨五入することは、質問自体の例にすぎません。IPアドレスを表現するためのより良い方法についてのあなたのコメントは非常に有効であり、最も意味があります。
-RolandoMySQLDBA

CHAR(15)は、bytesではなく15 文字を割り当てます。utf8の場合、これは45 バイトです。
リックジェームズ

2
これはCHAR / VARCHARの比較に関する良い答えですが、質問は異なるVARCHARサイズに関するものでした。
コレクター

13

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

  1. 結果(GROUP BYステートメントなど)をフィルターする一時テーブルを作成する場合、完全な長さが割り当てられます。

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

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

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


指摘する価値があります。MySQL 5.7は、ソートバッファー(可変長)に値をパックできます。ここで詳細に説明します: mysqlserverteam.com/…–
モーガン

9

このスレッドの回答のほとんどは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、この回答の一部は修正する必要があります。)


6

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


それは非常に新鮮な視点です。これがあなたが参照している本である場合(amazon.com/MySQL-High-Availability-Building-Centers/dp/…)、本のページ番号を答えに入れてください。+1 !!!
-RolandoMySQLDBA

ばかげた…高可用性ではなく高パフォーマンス:amazon.com/High-Performance-MySQL-Optimization-Replication/dp/……ページ番号は236/237です。ただし、この本は5.1のリリース直後に書き戻されたものであることに注意してください。5.5のすべてのBIGの変更を含む第3版が来年公開されるため、変更される可能性があります:)
TechieGurl

ページ236は、特定の文字セットに属する照合に言及しています。これはVARCHARにとっては厄介なことです。237ページで、クライアント/サーバー通信の設定と238ページの図5-5に別の理由が示されています。文字セットを前後に変換するプロセス。再び、VARCHARの別の厄介な冒険。
RolandoMySQLDBA

明確にするために、このセクションではMySQLがサイズを作成することを明確に述べていませんが、操作に一時テーブルが必要な場合、そのテーブルはMEMORY Engineにあり、文字列型を常に修正チャンクに格納するため、寛大であることがわかります定義は、RAMでの滞在とは対照的に、ディスクに行くために必要なメモリの一時テーブルを引き起こす可能性があります
TechieGurl

@RolandoMySQLDBA。うん...それも...照合もここ(あなたはUTF-8を使用し、非ラテン文字を持っているESPの場合)要因となると、ディスクへの迅速化への旅行にメモリエンジンテーブルとリードを扱うとき、それはすべてちょうど屋を殺す
TechieGurl

5

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


3

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

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

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

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