2009-09-22 18 views
40

Abbiamo una tabella con una chiave primaria composta composta da tre campi (ed è in MySQL 5.1). Ci sono circa 200 inserti e 200 selezioni al secondo su questa tabella, e la dimensione della tabella è di circa 1 milione di righe e sta aumentando.Limite delle prestazioni della chiave primaria composita in MySQL

La mia domanda è: la "chiave primaria composta" diminuisce le prestazioni degli inserti e dei selezioni su questa tabella?

Dovrei utilizzare un semplice campo ID INT a incremento automatico invece di una chiave primaria composta? (Penso che la risposta è molto legato al modo in cui MySQL gestisce gli indici su più colonne)

risposta

50

INSERT e UPDATE prestazioni varia poco: sarà quasi uguale per (INT) e (INT, INT) chiavi.

SELECT prestazioni del composito PRIMARY KEY dipende da molti fattori.

Se la tabella è InnoDB, la tabella viene aggregata in modo implicito nel valore PRIMARY KEY.

Ciò significa che la ricerca di entrambi i valori sarà più veloce se entrambi i valori comprendono la chiave: non sarà richiesta alcuna ricerca aggiuntiva di chiave.

Supponendo che la vostra richiesta è qualcosa di simile:

SELECT * 
FROM mytable 
WHERE col1 = @value1 
     AND col2 = @value2 

e il layout della tabella è questa:

CREATE TABLE mytable (
     col1 INT NOT NULL, 
     col2 INT NOT NULL, 
     data VARCHAR(200) NOT NULL, 
     PRIMARY KEY pk_mytable (col1, col2) 
) ENGINE=InnoDB 

, il motore avrà solo bisogno di ricercare il valore della chiave esatto nella tabella stessa.

Se si utilizza un campo autoincrement come un documento falso:

CREATE TABLE mytable (
     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
     col1 INT NOT NULL, 
     col2 INT NOT NULL, 
     data VARCHAR(200) NOT NULL, 
     UNIQUE KEY ix_mytable_col1_col2 (col1, col2) 
) ENGINE=InnoDB 

, poi il motore avrà bisogno, in primo luogo, di ricercare i valori del (col1, col2) nell'indice ix_mytable_col1_col2, recuperare il puntatore di riga dall'indice (il valore di id) e fare un'altra ricerca con id nella tabella stessa.

Per le tabelle MyISAM, tuttavia, questo non fa alcuna differenza, perché le tabelle MyISAM sono organizzate in heap e il puntatore di riga è solo offset di file.

In entrambi i casi, verrà creato uno stesso indice (per PRIMARY KEY o per UNIQUE KEY) e verrà utilizzato allo stesso modo.

+0

+1. Grazie, molto ben spiegato. – Fr0zenFyr

2
  1. Avere quella chiave primaria composita rallenta leggermente SELECT s, anche se l'effetto è praticamente trascurabile e non vale la pena preoccuparsi.
  2. Avendo quelle colonne indicizzate su tutti rallenta il tuo INSERT s, e certamente stai facendo abbastanza INSERT s per preoccuparsene. Questo è molto più preoccupante se si tratta di una tabella MyISAM, dove un INSERT blocca la tabella, piuttosto che se si tratta di una tabella InnoDB. Se, andando con la chiave primaria auto_increment, potresti lasciare quelle colonne non indicizzate, trarrai beneficio dal cambiamento.Se avresti ancora bisogno di mantenere le tre colonne indicizzate, anche se (per esempio, se devi forzare l'unicità sulla combinazione di esse), non farà nulla per te in termini di prestazioni.
22

Se è InnoDB, la chiave primaria composta verrà inclusa in ogni voce in ciascuno degli indici secondari.

Ciò significa che

  • I suoi indici secondari occuperanno tanto spazio quanto quelle colonne + tutte le colonne nella chiave
  • È possibile utilizzare un indice secondario primario come un indice di copertura se tutte le colonne richiesti sono contenuti nell'indice secondario + pk

Questi sono, ovviamente, uno svantaggio e un vantaggio rispettivamente.

chiavi primarie composite non sono necessariamente un male, a volte possono essere davvero utile perché InnoDB li raggruppa - il che significa che (disco-bound) varia scansioni sopra il PK possono essere soddisfatti utilizzando un numero inferiore di operazioni di IO di quanto sarebbe necessario su un indice non in cluster.

Ovviamente se hai chiavi esterne in altri tavoli, sono più ampie e devono includere l'intera chiave dalla tabella principale.

Ma direi a conti fatti, in generale, no. Avere una chiave primaria composta NON causa un problema da solo. Avere una chiave primaria "grande" (ad esempio grandi varchar) può tuttavia, se questo supera i vantaggi del clustering e la possibilità di utilizzare indici di copertura.

+0

Significa che se ho la mia chiave primaria su '(reviewId, userId)' e un indice secondario su '(userId)', questo indice contiene internamente '(userId, reviewId, userId)'? – Benjamin

+0

@ Benjamin Sì, hai ragione. È chiaramente indicato qui http://dev.mysql.com/doc/refman/5.7/en/innodb-index-types.html e in questo libro http://shop.oreilly.com/product/0636920022343.do –

Problemi correlati