MySQL:大きな列に対する一意の制約


10

VARCHAR最大3071文字を保持できる列を含むInnoDBテーブルを作成しようとしています。UNIQUEこの列のデータに制約を課したいのですが。

MySQLはインデックスを使用して制約を強制しているようです。InnoDBでは、インデックスサイズは767バイトに制限されているように見えます- VARCHAR(3071)データを保持している列には十分ではありません。

最大データ長やInnoDBの使用に妥協することなく、データベースにデータの一意性を強制する方法についての考えはありますか?

回答:


10

巨大なgen_clust_index(内部クラスタ化インデックス)は必要ありません。セカンダリインデックスであっても、そのサイズは信じられないほど巨大です。

事前にキーをチェックするために、トリガーまたはストアドプロシージャを使用する必要がある場合があります。

フィールドを使用してSHA1関数呼び出しを実行することも考えられVARCHAR(3071)ます。SHA1は40文字のフィールドを返します。このハッシュは、インデックスを作成するために必要なものだけかもしれません。

これがあるとしましょう

CREATE TABLE mytable
(
    id int not null auto_increment,
    txt VARCHAR(3071),
    primary key (id)
) ENGINE=InnODB;

そして、あなたUNIQUEはtxtでインデックスを作成したいと思います。SHA1アプローチを試す

CREATE TABLE mytablenew LIKE mytable;
ALTER TABLE mytable ADD txtsha1 CHAR(40);
ALTER TABLE mytable ADD UNIQUE KEY (txtsha1);
INSERT INTO mytablenew (id,txt,txtsha1)
SELECT id,txt,SHA1(txt) FROM mytable;

次に、それらを数えます

SELECT COUNT(1) FROM mytable;
SELECT COUNT(1) FROM mytablenew;

カウントが同じ場合、おめでとうございます!!! これで、長さ40の一意のインデックスが作成されました。次のように仕上げることができます。

ALTER TABLE mytable RENAME mytableold;
ALTER TABLE mytablenew RENAME mytable;
DROP TABLE mytableold;

以下のコメントで指摘されているように、これはより原子的になる可能性があります:

RENAME TABLE mytable TO mytableold, mytablenew TO mytable;
DROP TABLE mytableold;

この大きな列を使用する予定の任意のテーブルでこれを実行します。のデータとともにデータのSHA1を追加することを忘れないでくださいINSERT

重複するキーのオッズは2分の1から160乗です(その1.4615016373309029182036848327163e + 48。正確な数値が得られれば、いつか投稿します)。

試してみる !!!


+1これは基本的に非常に良いアイデアです!2つのダイジェストが同じかどうか、コンテンツも同じかどうか、JavaのHashMapが正確にどのように機能するかをチェックするトリガーと組み合わせます
ppeterka

1
Rolando-私は多くの問題を抱えています:(1)sha1はASCIIではなく、UTF8でなければなりません。(2)HEX()およびUNHEX()を使用する場合、sha1はBINARY(20)になる可能性があります。(3)ダウンタイムなしでリネームをアトミックにするには、RENAME TABLE mytable TO mytableold、mytablenew TO mytableを実行します。満足したらDROP TABLE mytableoldを実行します。(4)引用されているオッズは単一の行のものです。(5)2 64は間違っている-それは2だテーブルの160(6)オッズについてです:「2内の1つのチャンスがある2とテーブルという53 53行がDUP SHA1を持つことになりますが。」(6a)メガ宝くじで収集している間、小惑星に近づく可能性が高くなります。
リックジェームズ

@RickJames指摘されたすべてのポイント。ポイント5の私の悪い数学を許しなさい、それは2 ^ 160です。私は私の答えで#3を調整しました。
RolandoMySQLDBA 2012年

1
皆さん、あなたが提示するオッズは次のことを前提としています:1. SHAは完全な分布を持っています。2.入力は完全にランダムです。SHAには完全な配布はありません。他のハッシュアルゴリズムも行いません。入力は完全にランダムではなく、SHAは他のダイジェストと同様に、入力の小さな変化に対して出力に大きな変化を引き起こしますが、一部の入力のセットが同じ出力を生成し、それらの入力に系統的なものがあることは完全に可能ですそれらの間の接続。オッズ非常に低いので、今、私はほとんどここでバブリングしています。しかし、それでも、警戒すべきです。
Shlomi Noach

@ShlomiNoachハッシュキーは、面倒な場合があります。このレートでは、してもパスワード機能は、許容可能である(palominodb.com/blog/2011/12/04/hashing-algorithm-mysql-password
RolandoMySQLDBA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.