CodeLab技術ブログ

プログラミング技術まとめ

[MySQL]DBの高速重複チェック

DBにデータを入れる際に、同一データがないかどうかチェックをしなければならない場合。
単純に、同じ名前の人がいるか?というようなものだったら単純にselect文を発行してチェックすればよい。
(まぁ、名前の漢字が違うとか、電話番号のフォーマットが違うとか、そういうのがなければの話ですが)

複数のカラム、テーブルにまたがる場合はどうでしょうか?
インデックスされていないカラムを含む場合はすごく時間がかかるはずです。
テーブルが複数の場合、テーブル数分だけI/O処理がよけいに走り、これもまた処理が遅くなる一因となります。

ということで、すべてのキーが完全一致した場合に重複したとみなす。という条件で、高速でデータの重複チェックする方法を紹介したいと思います。

前提
テーブル名:table_a
カラムid,a1,a2,a3…
テーブル名:table_b
カラムid,b1,b2,b3…
table_aとtable_bはidをPKとして1:1の関係であるとし、各テーブルのa1,a2,a3,b1,b2,b3すべてが完全一致するデータがDB上に存在するかどうかのチェックを行うことを考えてみます。

重複チェック用のテーブルを用意します
nayose_table
id,md5(VARCHER 32)
(idをPKとしてtable_aやtable_bと1:1の関係。md5カラムもインデックス化しておきます)

次にデータinsert時にnayose_tableにもデータを入れます。
内容は、a1~b3をすべて連想配列にぶち込んでシリアライズ化。シリアライズ化したデータをハッシュ化(MD5等で)してmd5カラムに入れておきます。

重複チェック時にも挿入するデータで同じ計算を行いnayose_tableのmd5カラムに検索をかければ、同一データがあるあどうかチェックできるはずです。
キーとなるテーブル数やカラム数がいくら増えても、検索をかけるのは32バイトのデータなのでパフォーマンスに大きな影響は出ないはずです。
I/O処理もnayose_tableの読み込みだけなので劇的に少なくなるはずです。

データ件数が増えてしまった場合には、md5の先頭2バイトを取り出し、10進数に変換すれば0~256になります。この値もnayose_table入れておき
これをキーとしてパーティショニングを行えば、検索処理速度は理論上1/256となるはずです。

注意点としてはキーとなるカラムの値が変更された場合はnayose_tableも再計算する必要があります。