ようこそ!浜村拓夫の世界へ

    ブログ内検索

    最近の記事

    ブックマーク数の多い記事

    Blog Translation

    Powered By FC2ブログ

    Powered By FC2ブログ
    ブログやるならFC2ブログ


    FC2ブログ LOGIN

    with Ajax Amazon

    MySQLでTEXT型にUNIQUEなインデックスを張る方法

    このエントリーを含むはてなブックマーク はてなブックマーク - MySQLでTEXT型にUNIQUEなインデックスを張る方法 あとで読む
    MySQLでTEXT型に、UNIQUEなインデックスを張る方法がありませんでした。
    代替案として、TEXT型のデータのハッシュ値に、UNIQUEなインデックスを張る方法を考えました。

    ●エラー
    こんなん、出ましたー!

    MySQLでBLOB/TEXT型カラムにインデックスを張る | dTblog

    MySQL で新たにテーブルを作ったり、プライマリキー、ユニーク制約、またはインデックスを作成する際、下記のようなエラーが発生することがあります。

    ERROR 1170 (42000): BLOB/TEXT column 'text_field' used in key specification without a key length

    このエラーは、MySQL が BLOB型もしくはTEXT型 (これらに順ずる TINYTEXT型 や LONGTEXT型を含む)のような可変長カラムでは、その先頭から最大255文字分しかインデックスできないという制約から来ているようです。
    解決策は上記のとおり、キー長を明示するか、変わりに255以下で VARCHAR(100) のようなカラムを使って、そちらをインデックスとして使うといった工夫が考えられます。



    そーなんですよ!

    ・TEXT型の「text_field」カラムには、インデックスを張らない。
    ・VARCHAR型の「text_field_hash」カラムを用意して、UNIQUEなインデックスを張る。
    という方法で対処してみました。


    ●ハッシュ関数
    問題は、ハッシュ値が短いと、衝突の可能性が高くなることですね。
    PHPの場合なら、128バイト長のハッシュ値を生成する「SHA512」というアルゴリズムが良いと思います。

    PHPのhash関数で使えるアルゴリズムとハッシュ化後の文字数 - new takyam();

    アルゴリズム ハッシュ後の文字数
    sha512 128



    PHP: Hash 関数 - Manual
    PHP: crypt - Manual
    計算速度と桁数で、お好みのアルゴリズムをチョイス!


    16^128(16の128乗)=2^512(2の512乗)=1.340781e+154=13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096≠154桁程度の数字です。

    16進数で128桁の数字は、2進数で512桁であり、10進数なら154桁程度の数になるんですね。
    これでも足りない場合は、衝突の可能性をさらに下げるために、元データの一部をソルトとして使えば良いと思います。


    ●ソルト
    PHP: パスワードのハッシュ - Manual

    ソルトとは?

    暗号理論におけるソルトとは、ハッシュ処理の際に追加するデータのことです。
    事前に計算済みのハッシュとその元入力の対応表 (レインボーテーブル) で出力を解析される可能性を減らすために利用します。

    端的に言うと、ソルトとはちょっとした追加データです。
    これをつけるだけで、ハッシュをクラックするのが劇的に難しくなります。
    事前に計算済みのハッシュとその元入力を大量にまとめた表が、オンラインで多数公開されています。
    ソルトを使えば、そのハッシュ値がこれらの表に含まれている可能性を大きく減らすことができます。



    (例)
    ・元文1「AAAA」
    ・元文2「BBBB」
    をハッシュ関数Fでハッシュ値を求めたら、同じハッシュ値「ZZZZ」が得られた。
    =ハッシュ値の衝突。

    元文の一部(「AA」とか「BB」)をソルト(追加データ)として使い、もう一度ハッシュ値を取得する。

    ・「AAZZZZ」→ 「XXXX」
    ・「BBZZZZ」→ 「YYYY」
    これで衝突が回避された。

    「AAAA」や「BBBB」以外の、他のデータと衝突する可能性を下げるために、
    ・「AAAA」→「ZZZZXXXX」
    ・「BBBB」→「ZZZZYYYY」
    をハッシュ値として保存すれば良い。

    とりあえず、今回の用途なら、10の150乗もあれば十分だな。
    よし!これで行ってみよう!

    関連記事

    コメント

    コメントの投稿


    管理者にだけ表示を許可する

    トラックバック

    トラックバックURL:
    http://hamamuratakuo.blog61.fc2.com/tb.php/963-f7462713

    FC2Ad