2013-06-06 13 views
7

Ho un tavolo chiamato events dove passano tutte le nuove informazioni. Questa tabella funziona come riferimento per tutte le query per i feed di notizie, quindi gli elementi degli eventi vengono selezionati da lì e le informazioni corrispondenti a quell'evento vengono recuperate dalle tabelle corrette.Come avere ID univoci su due o più tabelle in MySQL?

Ora, ecco il mio problema. Ho E_ID nella tabella degli eventi che corrisponde all'ID di un evento in una tabella diversa, sia T_ID per tracks, e così via ... Questi ID potrebbero essere gli stessi quindi per il momento sono solo ha utilizzato un diverso valore auto_increment per ogni tabella, pertanto status è stato avviato su 500 tracks su 0 ecc. Ovviamente, non voglio farlo perché non ho ancora idea di quale tabella avrà il maggior numero di dati al suo interno. Assumerei che lo status supererebbe rapidamente lo tracks.

Le informazioni vengono inserite nella tabella event con trigger. Ecco un esempio di uno;

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

che quelli per lui tabella di stato.

C'è un aggiunta a ciò grilletto posso fare per garantire la NEW.S_ID! = Un E_ID attualmente in events e se non cambia il S_ID conseguenza.

alternativa, c'è qualche tipo di chiave posso utilizzare per fare riferimento eventi quando automatico incrementando il S_ID modo che il S_ID non viene incrementato di un valore di E_ID.

Questi sono i miei pensieri, penso che quest'ultima soluzione sarebbe meglio ma dubito che sia possibile o lo sia ma richiederebbe un'altra tabella di riferimento e sarebbe troppo complessa.

+4

Suggerirei che se hai davvero bisogno di questi, assegni l'id a s un campo di incremento automatico su una tabella e usa il valore da questo come nuovo id quando si popola un campo sulle varie altre tabelle. Tuttavia preferirei avere i campi id sui vari tavoli totalmente indipendenti. – Kickstart

risposta

12

È davvero raro richiedere un ID univoco sui tavoli, ma ecco una soluzione che lo farà.

/* 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, ...); 

Ovviamente, si potrebbe duplicare la struttura della tabella events per le altre tabelle.

+0

So che è vecchio, e mentre l'inserimento è coperto, ma la cancellazione (e la modifica) sembra un po 'più difficile. Inoltre, in tutti i casi ha richiesto disciplina dall'applicazione. Sembra che una soluzione con trigger possa essere una via, proprio al di là di me in questo momento. – swa66

+0

I trigger potrebbero funzionare per la cancellazione, se necessario. Tuttavia, non riesco a pensare a una soluzione DB in cui la cancellazione permanente debba essere richiesta. Un flag di stato "is_active" sugli oggetti dovrebbe essere adatto al 99% dei casi. –

3

Si potrebbe anche utilizzare solo un identificatore univoco universale (UUID).

Un UUID è progettato come un numero che è globalmente unico nello spazio e nel tempo. Due chiamate a UUID() dovrebbero generare due valori diversi, anche se queste chiamate vengono eseguite su due computer separati che non sono collegati tra loro.

Si prega di leggere di più su di esso nel manual.

C'è anche un shorter version.

+4

Lo svantaggio di utilizzare gli UUID è che quando la tabella aumenta di dimensioni, l'inserimento diventa estremamente lento. Poiché il tuo ID è la tua chiave primaria, è il tuo indice cluster. Ogni volta che inserisci un UUID, l'intera struttura della tabella dovrà essere ricorsa. Questo può richiedere MINUTES quando ottieni una tabella con milioni di record. Un valore di auto-incremento andrà sempre alla fine, quindi non è necessario ricorrere. –

+0

@StevenMoseley Che ne dici di utilizzare un bigint come chiave primaria e utilizzare un UUID come colonna secondaria? Non applicheresti l'integrità, lo assumeresti solo, ma a seconda delle tue esigenze potrebbe essere sufficiente. Nel peggiore dei casi è possibile verificare manualmente l'UUID duplicato quando è necessario quel livello di certezza, ad esempio se i dati vengono inseriti da una chiamata API esterna e non si è sicuri di dove/come è stato generato l'UUID. –

+0

@ Le-roy solo vedendo questa domanda. Gli svantaggi di questo sono: 1) si creerebbe un indice cluster "throw-away". In MySQL, l'indice primario (in cluster) è DI FAR il più veloce per il tempo di ricerca, perché i dati sono effettivamente ordinati in quell'ordine, mentre tutti gli altri tipi di indice contengono puntatori ai dati ... 2) l'indice UUID stesso verrà ordinato sull'inserto, che renderà gli inserimenti più lenti, anche se non tanto quanto l'UUID PK), e ... 3) infine, un UUID ha 9 volte la dimensione di un INT. Gli indici MySQL occupano già molto spazio su disco. Perché complicarli rendendoli 9 volte più grandi di quanto debbano essere? –

0

UUID_SHORT() dovrebbe fare il trucco. Genera per te interi senza segno a 64 bit.

Secondo il documento logica generatore è:

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

Il valore di UUID_SHORT() è garantito per essere unico se le seguenti condizioni:

  • Il valore server_id di il server corrente è compreso tra 0 e 255 ed è univoco tra i tuoi server master e slave

  • Y ou non arretrato l'ora di sistema per il vostro host server tra mysqld riavvia

  • Invochi UUID_SHORT(), in media, meno di 16 milioni di volte al secondo tra mysqld riavvia

mysql> SELECT UUID_SHORT(); 
    -> 92395783831158784 

Se sei curioso di sapere qual è il tuo id server, puoi utilizzare uno di questi:

SELECT @@server_id 
SHOW VARIABLES LIKE 'server_id';