2011-12-21 6 views
6

Evitare l'uso di IN (...) quando si seleziona su campi indicizzati, Si interrompe la prestazione della query SELECT.Perché usare IN (...) quando si seleziona su campi indicizzati, uccide le prestazioni della query SELECT?

ho trovato questo qui: https://wikis.oracle.com/pages/viewpage.action?pageId=27263381

Puoi spiegarlo? Perché questo ucciderà le prestazioni? E cosa dovrei usare al posto di IN. "OR" forse?

+0

@BillKarwin paging ... – ajreal

+0

+1 per il collegamento =) – newtover

risposta

-1

Credo che IN sia trattato allo stesso modo di un gruppo di OR, quindi l'utilizzo di OR non aiuterà.

Un'alternativa è creare una tabella temporanea per contenere i valori della clausola IN e quindi unirsi a quella tabella temporanea in SELECT.

Ad esempio:

CREATE TEMPORARY TABLE temp_table (v VARCHAR) 

INSERT INTO temp_table VALUES ('foo') 
INSERT INTO temp_table VALUES ('bar') 

SELECT * FROM temp_table tmp, orig_table orig 
WHERE temp_table.v = orig.value 

DROP TEMPORARY TABLE temp_table 
2

Perché MySQL non può ottimizzarlo.

Ecco un esempio: (. Spiacente per collegamento esterno non mostra correttamente qui)

explain select * from keywordmaster where id in (1, 567899); 

plan

qui un'altra domanda:

explain 
    select * from table where id = 1 
    union 
    select * from keywordmaster where id = 567899 

plan

Come potete vedere nella seconda query che otteniamo ref come const e type è const anziché range. MySQL non può ottimizzare le scansioni di intervallo.

+0

tuttavia, la seconda query sembra richiedere più tempo, almeno, sui miei set di dati. – newtover

+0

@newtover si applica solo 'quando si seleziona su campi indicizzati' –

+1

Ho anche controllato http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/0596101716, e afferma: "L'output di EXPLAIN può a volte è difficile dire se MySQL è davvero alla ricerca di una gamma di valori o di un elenco di valori ... Non siamo solo schizzinosi: questi due tipi di accesso agli indici hanno prestazioni diverse. qualsiasi ulteriore colonna nell'indice, ma la condizione di uguaglianza multipla non ha questa limitazione. " – newtover

3

A dire la verità, questa affermazione contraddice molti indizi che ho letto su libri e articoli su MySQL.

Ecco un esempio: http://www.mysqlperformanceblog.com/2010/01/09/getting-around-optimizer-limitations-with-an-in-list/

Inoltre, expr IN(value, ...) stessa ha ulteriori miglioramenti per la gestione dei grandi liste valori, in quanto si suppone per essere usato come una valida alternativa ad alcune range query:

Se tutti i valori sono costanti, vengono valutati in base al tipo di expr e ordinati. La ricerca dell'elemento viene quindi eseguita utilizzando una ricerca binaria. Ciò significa che IN è molto veloce se la lista valori IN è composta interamente da costanti.

L'utilizzo eccessivo dell'IN può causare interrogazioni lente. Alcuni casi sono annotati in the article.

0

Prior to MySQL 5.0 sembra che mySQL utilizzerebbe un solo indice per una tabella. Quindi, se avessi uno SELECT * FROM tbl WHERE (a = 6 OR b = 33), potrebbe scegliere di utilizzare l'indice o l'indice b, ma non entrambi. Si noti che si dice campi, plurale. Ho il sospetto che il consiglio viene da quel momento e il work-around è stato quello di unione o risultati, in questo modo:

SELECT * FROM tbl WHERE (a = 6) 
UNION 
SELECT * FROM tbl WHERE (b = 33) 
Problemi correlati