2013-06-06 14 views
7

私はeventsと呼ばれるテーブルを持っています。この表は、ニュース項目のすべての照会の参照として機能し、そこでイベント項目が選択され、そのイベントに対応する情報が正しい表から検索されます。MySQLで2つ以上のテーブルに一意のIDを持たせるには?

ここに私の問題があります。私はE_IDをイベントテーブルに入れて、別のテーブルのイベントのIDに対応しています。T_IDtracksS_IDstatusなどです...これらのIDは当分の間は同じですテーブルごとに異なるauto_increment値を使用しました。statusが0からtracksなどで開始されました。明らかに、どのテーブルがその中に最も多くのデータを持つのかまだ分かりません。私はstatusがすぐにtracksを超えると仮定します。

この情報は、トリガーを使用してeventテーブルに挿入されます。ここに1つの例があります。

BEGIN 
INSERT INTO events (action, E_ID, ID) 
VALUES ('has some news.', NEW.S_ID, NEW.ID); 
END 

ステータステーブル用のものです。

私はNEW.S_IDを確保するために作ることができるトリガに加えがあります!= eventsで現在E_IDとそれに応じS_IDを変えなければ。

また、自動S_IDE_IDの値にインクリメントされないようにS_IDをインクリメントするとき、私は、イベントを参照するために使用できるキーのいくつかの種類があります。

これは私の考えですが、私は後者の方が良いでしょうが、それが可能であるとは思っていませんが、別の参照テーブルが必要で、複雑すぎます。

+4

これらのIDが本当に必要な場合は、 1つのテーブルに自動増分フィールドを追加し、他のさまざまなテーブルにフィールドを移入するときにそのIDを新しいIDとして使用します。しかし、私はさまざまなテーブルにIDフィールドを完全に独立させることを好むでしょう。 – Kickstart

答えて

12

テーブル間で一意のIDを必要とするのは本当に珍しいことですが、これを行うソリューションはここにあります。

/* Create a single table to store unique IDs */ 
CREATE TABLE object_ids (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    object_type ENUM('event', ...) NOT NULL 
) ENGINE=InnoDB; 

/* Independent object tables do not auto-increment, and have a FK to the object_ids table */ 
CREATE TABLE events (
    id INT UNSIGNED NOT NULL PRIMARY KEY, 
    ... 
    CONSTRAINT FOREIGN KEY (id) REFERENCES object_ids (id) 
) ENGINE=InnoDB; 

/* When creating a new record, first insert your object type into the object_ids table */ 
INSERT INTO object_ids(object_type) VALUES ('event'); 
/* Then, get the auto-increment id. */ 
SET @id = LAST_INSERT_ID(); 
/* And finally, create your object record. */ 
INSERT INTO events (id, ...) VALUES (@id, ...); 

もちろん、あなたが他のテーブルのためのeventsテーブルの構造を複製します。

+0

私はそれが古いことを知っていますが、挿入はカバーされていますが、削除(および変更)はやや難しいようです。それだけでなく、すべてのケースでアプリケーションから規律が必要でした。それはトリガーが私のすぐそばにある道である可能性のある解決策のように感じます。 – swa66

+0

必要に応じて、トリガーを削除することができます。ただし、永続的な削除が必要なDBソリューションは考えられません。オブジェクトの "is_active"ステータスフラグは、99%のケースに適しているはずです。 –

3

ユニバーサルユニークID(UUID)を使用することもできます。

UUIDは、時空間でグローバルに一意の番号として設計されています。 UUID()への2回の呼び出しは、たとえこれらの呼び出しが相互に接続されていない2台の別々のコンピューターで実行されたとしても、2つの異なる値を生成すると予想されます。

詳細については、manualを参照してください。

shorter versionもあります。

+4

UUIDを使用することの欠点は、テーブルのサイズが大きくなると挿入が極端に遅くなることです。 IDは主キーなので、クラスタ化インデックスです。あなたがUUIDを挿入するたびに、テーブル構造全体が再利用されなければなりません。これは、数百万のレコードを持つテーブルを取得するときには、数分かかることがあります。自動インクリメントの値は常に最後になりますので、頼りなくなる必要はありません。 –

+0

@StevenMoseleyプライマリキーとしてbigintを使用し、UUIDをセカンダリカラムとして使用するとどうなりますか?あなたは完全性を強制するつもりはないでしょう、あなたはそれを仮定しているだけですが、必要に応じて十分であるかもしれません。最悪のケースでは、確実にレベルが必要な場合、つまりデータが外部API呼び出しから挿入されていて、UUIDの生成場所や方法がわからない場合は、重複するUUIDを手動でチェックできます。 –

+0

@ Le-royはこの質問をちょうど見ています。その欠点は次のとおりです。1)「スローアウェイ」クラスター化インデックスを作成することになります。 MySQLでは、データが実際にその順序でソートされているので、プライマリ(クラスタ化された)インデックスはシーク時間が最も早いですが、他のすべてのインデックスタイプにはデータへのポインタが含まれています... 2)UUIDインデックス自体がソートされますPKU UUIDほどではないにしても、挿入を遅くします)、そして... 3)最後に、UUIDはINTの9倍のサイズを持っています。 MySQLインデックスは既に多くのディスク容量を占めています。なぜ彼らは必要以上に9倍大きくすることによってそれらを複雑にするのですか? –

0

UUID_SHORT()はすべきことです。 64ビットの符号なし整数が生成されます。

ドキュメントによれば、発電機ロジックは次の条件が成立した場合

(server_id & 255) << 56 
+ (server_startup_time_in_seconds << 24) 
+ incremented_variable++; 

UUID_SHORT(の値)が一意であることが保証される。

  • のSERVER_ID値現在のサーバーは0〜255の間であり、マスタサーバーとスレーブサーバーのセットの中で一意です。

  • Y mysqldの間の毎秒の平均16未満の万回のOUのmysqldの間、サーバーのホストが

  • を再起動するためにあなたが(UUID_SHORTを呼び出すシステム時刻をバックに設定していないが)場合

mysql> SELECT UUID_SHORT(); 
    -> 92395783831158784 

を再起動しますあなたの好きなサーバIDは何ですか?

SELECT @@server_id 
SHOW VARIABLES LIKE 'server_id'; 
関連する問題