2009-11-21 12 views
6

Ultimamente ho pensato ai miei indici di database, in passato mi sono semplicemente scordato in modo non cauto in un secondo momento, e non ci ho mai pensato molto se sono corretti o anche aiutando. Ho letto informazioni contrastanti, alcuni dicono che più indici sono migliori e altri che troppi indici sono cattivi, quindi spero di ottenere qualche chiarimento e di imparare un po 'qui.Ho bisogno di un po 'di chiarimenti sugli indici MySQL

Diciamo che ho questo ipotetico tavolo:

CREATE TABLE widgets (
    widget_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    widget_name VARCHAR(50) NOT NULL, 
    widget_part_number VARCHAR(20) NOT NULL, 
    widget_price FLOAT NOT NULL, 
    widget_description TEXT NOT NULL 
); 

avrei tipicamente aggiungere un indice per i campi che verranno unite e campi che saranno ordinati il ​​più delle volte:

ALTER TABLE widgets ADD INDEX widget_name_index(widget_name); 

Così ora , in una ricerca del tipo:

SELECT w.* FROM widgets AS w ORDER BY w.widget_name ASC 

Il widget_name_index è utilizzato per Sor t il set di risultati.

Ora, se posso aggiungere un parametro di ricerca:

SELECT w.* FROM widgets AS w 
WHERE w.widget_price > 100.00 
ORDER BY w.widget_name ASC 

Credo che ho bisogno di un nuovo indice.

ALTER TABLE widgets ADD INDEX widget_price_index(widget_price); 

Ma, utilizzerà entrambi gli indici? A quanto mi risulta non lo farà ...

ALTER TABLE widgets ADD INDEX widget_price_name_index(widget_price, widget_name); 

Ora widget_price_name_index saranno utilizzati sia per selezionare e ordinare i record. Ma cosa succede se voglio girare intorno e fare questo:

SELECT w.* FROM widgets AS w 
WHERE w.widget_name LIKE '%foobar%' 
ORDER BY w.widget_price ASC 

Sarà widget_price_name_index essere utilizzato per questo? O ho anche bisogno di un widget_name_price_index?

ALTER TABLE widgets ADD INDEX widget_name_price_index(widget_name, widget_price); 

Ora che cosa se ho una casella di ricerca che cerca widget_name, widget_part_number e widget_description?

ALTER TABLE widgets 
ADD INDEX widget_search(widget_name, widget_part_number, widget_description); 

E se gli utenti finali possono ordinare in base a qualsiasi colonna? È facile vedere come potrei finire con più di una dozzina di indici per solo 5 colonne.

Se si aggiunge un altro tavolo:

CREATE TABLE specials (
    special_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    widget_id INT UNSIGNED NOT NULL, 
    special_title VARCHAR(100) NOT NULL, 
    special_discount FLOAT NOT NULL, 
    special_date DATE NOT NULL 
); 
ALTER TABLE specials ADD INDEX specials_widget_id_index(widget_id); 
ALTER TABLE specials ADD INDEX special_title_index(special_title); 

SELECT w.widget_name, s.special_title 
FROM widgets AS w 
INNER JOIN specials AS s ON w.widget_id=s.widget_id 
ORDER BY w.widget_name ASC, s.special_title ASC 

Io parto dal presupposto questo userà widget_id_index e l'indice chiave primaria widgets.widget_id per il join, ma per quanto riguarda l'ordinamento? Utilizzerà sia widget_name_index e special_title_index?

Io non voglio divagare troppo a lungo, ci sono un numero infinito di scenari che potrei confondere. Ovviamente questo può diventare molto più complesso con gli scenari del mondo reale piuttosto che con un paio di semplici tabelle. Qualsiasi chiarimento sarebbe apprezzato.

+4

Non metto questo come risposta dato che non sono un professionista quando si tratta di database, ma in mysql puoi usare EXPLAIN prima di una query per fornire alcune informazioni su quali indici sono usati. http://dev.mysql.com/doc/refman/5.0/en/explain.html – MitMaro

risposta

5

Secondo le migliori pratiche, non è necessario creare un indice durante la definizione degli schemi di tabella. È sempre preferibile creare un indice durante la creazione delle query nell'applicazione. Nella maggior parte dei casi, inizierai con un indice a colonna singola per soddisfare una query. Se si desidera utilizzare molte colonne in una query, è possibile creare un indice di copertura.

Un indice di copertura è un indice con due o più colonne in esso. Se l'indice soddisfa tutti i requisiti della colonna di una query, il motore di archiviazione può ottenere tutti i risultati dall'indice invece di eseguire il kicking in un'operazione di I/O su disco. Pertanto, quando si crea una query che utilizza più colonne, è possibile creare un nuovo indice che copra tutte le colonne richieste oppure, è possibile estendere l'indice esistente per includere più colonne.

È necessario prendere alcune considerazioni mentre si fa uno dei precedenti. MySQL considera un indice solo quando la colonna più a sinistra dell'indice può essere utilizzata nella query. Altrimenti, cerca semplicemente l'intera tabella per ottenere risultati. Pertanto, se è possibile estendere un indice esistente senza influire su tutte le query che utilizzano tale indice, sarebbe una scelta saggia. Altrimenti, puoi andare avanti e creare un nuovo indice per la nuova query. A volte, le query possono essere regolate per adattarsi alla struttura dell'indice.

+0

'invece di avviare un'operazione di I/O su disco 'Dove pensi che i dati dell'indice siano memorizzati? –

3

Un indice velocizza la selezione, ma rallenta inserti e aggiornamenti. Non è necessario creare un indice per ogni possibile combinazione di colonne che si possa immaginare. Di solito creo solo gli indici ovvi che so che userò spesso, e aggiungo solo di più se riesco a vedere che sono necessari dopo aver preso le misure delle prestazioni.Il database può ancora utilizzare un indice anche se non copre tutte le colonne della query.

+0

Altri indici potrebbero essere migliori. Troppi indici è decisamente peggio. –

3

In una query viene utilizzato sempre un solo indice. Fortunatamente, è possibile creare un indice che copre più colonne:

ALTER TABLE widgets ADD INDEX name_and_price_index(widget_name, widget_price); 

L'indice sopra sarà utilizzato se si seleziona dal WIDGET_NAME o WIDGET_NAME + widget_price (ma non solo widget_price).

Come indicato da MitMaro, utilizzare EXPLAIN su una query per vedere quali indici MySQL deve scegliere, nonché quale indice utilizzare. Vedi here per ulteriori dettagli.

+0

Le versioni recenti di MySQL hanno l'unione di indici, che può utilizzare diversi indici, in alcuni casi. – peufeu

Problemi correlati