MD5ハッシュを格納するインデックス列があります。したがって、列には常に32文字の値が格納されます。何らかの理由で、これはcharではなくvarcharとして作成されました。データベースを移行してcharに変換する手間をかける価値はありますか?これは、InnoDBを使用したMySQL 5.0にあります。
MD5ハッシュを格納するインデックス列があります。したがって、列には常に32文字の値が格納されます。何らかの理由で、これはcharではなくvarcharとして作成されました。データベースを移行してcharに変換する手間をかける価値はありますか?これは、InnoDBを使用したMySQL 5.0にあります。
回答:
同様の質問が以前に尋ねられました
これが私の答えの抜粋です
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)です。CHAR(15)
IPアドレスの長さはそれほど変わらず、追加のバイトで制御される文字列操作の複雑さが増すので、私はすぐに思いつきます。PROCEDURE ANALYSE()
そのような列に対してはまだできます。VARCHARを推奨することさえあります。この場合、私のお金はまだVARCHARよりCHARになります。
CHARとVARCHARの問題は、適切な計画を通してのみ解決できます。大きな力には大きな責任が伴います(決まり文句ですが真実です)。
更新
MD5に関してstrlen
は、行フォーマット全体を切り替えるときに内部の計算を削除する必要があります。フィールド定義を変更する必要はありません。
MD5キーが存在する唯一のVARCHARである場合、そのキーを使用して、テーブルの行形式をfixedに変換します。他にもかなりの数のVARCHARフィールドが存在する場合は、同様にメリットがあります。その代わりに、テーブルはそのサイズの約2倍に拡大します。ただし、追加の調整を行わなくても、クエリは約20%加速するはずです。
bit
とbinary
?
値ごとに1バイト、またはに変換することで約3%節約できるようですchar
。とにかく16進数でMD5を保存している場合は、おそらく価値がありません- binary
代わりにaを使用することで50%節約できます。
マルチバイト文字セットを使用している場合、32バイト以上を使用char(32)
できることを指摘してくれたOvais(コメントを参照)に感謝します。
このunhex
関数を使用して16進文字列をバイナリに変換する必要があることを指摘してくれたRick Jamesに感謝します。
create table foo(bar varbinary(100)); insert into foo(bar) values(md5('a')); insert into foo(bar) values(unhex(md5('a')));
select length(bar) from foo;
| 長さ(バー)| | ----------:| | 32 | | 16 |
db <> fiddle here
binary
-または誤解しましたか?
BINARY
使用しても、を使用しない限りほとんど動作しませんUNHEX()
。つまり、あなたが保存することができUNHEX(MD5(x))
、16バイトにBINARY(16)
保存する上で重要なスペースを節約するためMD5(x)
にCHAR(32) CHARACTER SET ascii
。
私の意見では変更する価値はありません。ここでドキュメントを見ると、この2つの違いがわかります。あなたの使用シナリオでは、行サイズに関連する余分なオーバーヘッドを本当に心配しない限り、一方は他方に対して実際に大きな利点を提供しません。
http://dev.mysql.com/doc/refman/5.0/en/char.html
上記のリンク先のドキュメントの最初のコメントにも注意してください。「CHARは、レコード全体が固定サイズの場合にのみアクセスを高速化します。つまり、可変サイズのオブジェクトを使用する場合は、可変サイズ。VARCHARも含まれているテーブルでCHARを使用しても速度が向上しない