2010-09-05 10 views
8

Ho due tabelle di database: "luoghi" e "traduzioni". Le traduzioni di luoghi nomi sono realizzati selezionando i record da "luoghi", che non hanno le traduzioni in lingua specificata ancora:SQL: Ottimizzazione o alternative della subquery "NOT IN"

SELECT `id`, `name` 
FROM `places` 
WHERE `id` NOT IN (SELECT `place_id` FROM `translations` WHERE `lang` = 'en') 

Questo ha funzionato benissimo con 7 000 registrazioni di posti, ma si è schiantato quando il numero delle traduzioni ha raggiunto 5 000. da allora, la query richiede circa 10 secondi e restituisce l'errore:

2006 - MySQL server has gone away

quanto ho capito, il problema principale qui è la sottoquery ritorno a molti risultati, bu come avrei potuto risolverlo, se devo selezionare tutti i posti che non sono ancora stati tradotti?

Il mio piano B è quello di creare un nuovo campo booleano nella tabella "places", chiamato "tradotto", e resettarlo su "false", ogni volta che cambio lingua - ciò impedirebbe il subquery. Tuttavia, forse potrei semplicemente modificare la mia attuale istruzione SQL e impedire di aggiungere campi aggiuntivi?

+1

Non una risposta, più di suggerimenti se è ancora possibile nella fase del tuo progetto. Quando ho quegli incessanti errori di "MySQL Server è andato via", ho portato la mia app su Postgresql. Mai guardato indietro dal – Hao

risposta

13

L'ovvia alternativa:

SELECT 
    `id`, `name` 
FROM 
    `places` 
WHERE 
    NOT EXISTS (
    SELECT 1 FROM `translations` WHERE `id` = `places`.`id` AND `lang` = 'en' 
) 

Ci dovrebbe essere un indice composto cluster sopra (translations.id, translations.lang) (composito significa: un singolo indice su più settori, cluster mezzi: l'indice governa come la tabella è ordinata).

+0

Grazie, è esattamente quello che mi mancava. – krn

+0

@Kernius: puoi postare quale differenza questo cambiamento ti fa al confronto? (l'indice è importante!) – Tomalak

+1

Avevo già indicizzato quei campi e avevo ancora quel problema, che semplicemente scompariva, quando passai al tuo suggerimento. – krn

0

In questo caso, ritengo che l'alternativa migliore sia fare due query separate. Memorizzare il risultato del primo in una variabile e usare il secondo.

Problemi correlati