2011-10-26 14 views
5

Ho una query mysql che ha 5 o 6 LEFT JOINS. Come previsto, questo è piuttosto lento. Considerando che mi aspetto solo ~ 100 risultati, potrebbe essere più sensato per me eseguire molte query SQL separate e unirle manualmente. Immagino che ci vorrà molto tempo a causa dell'enorme tabella creata con più join di sinistra. È giusto?Migliorare le prestazioni con LEFT JOIN

Lo sto facendo in Rails 3. So che creare record attivi è costoso, ma sto pensando che potrebbe essere più veloce di avere così tante LEFT JOIN. So molto poco su come funziona il database sotto il cofano. Apprezzerei davvero ogni intuizione


Edit: Ecco l'attuale query e tavolo schemi

Query

SELEZIONA people * FROM people LEFT JOIN person_organization_relationships ON person_organization_relationships .person_id = people .ID E person_organization_relationships.. stop_person IS NULL LEFT JOIN person_redirect_relationships AS r_from_others ON r_from_others.parent_id = people .ID E r_from_others.stop_person IS NULL LEFT JOIN person_redirect_relationships AS r_to_others ON r_to_others.child_id = people .ID E r_to_others.stop_person IS NULL LEFT JOIN person_organization_relationships AS r_p_check ON r_p_check.person_id = r_from_others. child_id E r_p_check.stop_person è lasciato NULL ENTRA organization_redirect_relationships AS r_o_check ON r_o_check.child_id = person_organization_relationships .organization_id E r_o_check.stop_organization è lasciato NULL ENTRA person_organization_relationships AS rr_p_check ON rr_p_check.person_id = r_from_others.child_i d E rr_p_check.stop_person è lasciato NULL ENTRA organization_redirect_relationships AS rr_o_check ON rr_p_check.organization_id = rr_o_check.child_id E rr_o_check.stop_organization IS NULL WHERE (((person_organization_relationships .organization_id = 1 o r_o_check.parent_id = 1) e r_to_others .parent_id IS NULL) O (r_p_check.organization_id = 1 o rr_o_check.parent_id = 1)) GROUP BY people .id

schema della tabella:

create_table "people", :force => true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.boolean "delta",    :default => true, :null => false 
    end 


    create_table "person_organization_relationships", :force => true do |t| 
    t.integer "person_id" 
    t.integer "organization_id" 
    t.integer "start_person" 
    t.integer "stop_person" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "person_organization_relationships", ["organization_id"], :name => "index_person_organization_relationships_on_organization_id" 
    add_index "person_organization_relationships", ["person_id"], :name => "index_person_organization_relationships_on_person_id" 
    add_index "person_organization_relationships", ["start_person"], :name => "index_person_organization_relationships_on_start_person" 
    add_index "person_organization_relationships", ["stop_person"], :name => "index_person_organization_relationships_on_stop_person" 

    create_table "person_redirect_relationships", :force => true do |t| 
    t.integer "parent_id" 
    t.integer "child_id" 
    t.integer "start_person" 
    t.integer "stop_person" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "person_redirect_relationships", ["child_id"], :name => "index_person_redirect_relationships_on_child_id" 
    add_index "person_redirect_relationships", ["parent_id"], :name => "index_person_redirect_relationships_on_parent_id" 
    add_index "person_redirect_relationships", ["start_person"], :name => "index_person_redirect_relationships_on_start_person" 
    add_index "person_redirect_relationships", ["stop_person"], :name => "index_person_redirect_relationships_on_stop_person" 


    create_table "organization_redirect_relationships", :force => true do |t| 
    t.integer "parent_id" 
    t.integer "child_id" 
    t.integer "start_organization" 
    t.integer "stop_organization" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "organization_redirect_relationships", ["child_id"], :name => "index_organization_redirect_relationships_on_child_id" 
    add_index "organization_redirect_relationships", ["parent_id"], :name => "index_organization_redirect_relationships_on_parent_id" 
    add_index "organization_redirect_relationships", ["start_organization"], :name => "index_organization_redirect_relationships_on_start_organization" 
    add_index "organization_redirect_relationships", ["stop_organization"], :name => "index_organization_redirect_relationships_on_stop_organization" 

Questa domanda non ha prodotto risultati.

+ ---- + ------------- + ------------------------ ----------- + -------- + ----------------------------- -------------------------------------------------- --------------------------------------- + ---------- --------------------------------------------- + ---- ----- + -------------------------------------------- ---------------------------- + ------ + -------------- ------------------- + | id | select_type | tabella | tipo | possibili_keys
| chiave | key_len | rif
| righe | Extra | + ---- + ------------- + ----------------------------- ------ + -------- + ---------------------------------- -------------------------------------------------- ---------------------------------- + --------------- ---------------------------------------- + --------- + ------------------------------------------------- ----------------------- + ------ + ------------------- -------------- + | 1 | SEMPLICE | persona_dettagli | TUTTI | index_person_details_on_current_p_id
| NULL | NULL | NULL
| 4938 | Uso temporaneo; Usando filesort | | 1 | SEMPLICE | persone | eq_ref | PRIMARIO
| PRIMARY | 4 | knolcano_development.person_details.current_p_id
| 1 | | | 1 | SEMPLICE | person_organization_relationships | ref | index_person_organization_relationships_on_person_id, index_person_organization_relationships_on_stop_person | index_person_organization_relationships_on_person_id | 5 | knolcano_development.person_details.current_p_id
| 1 | | | 1 | SEMPLICE | r_from_others | ref | index_person_redirect_relationships_on_parent_id, index_person_redirect_relationships_on_stop_person | index_person_redirect_relationships_on_stop_person | 5 | const
| 3 | | | 1 | SEMPLICE | r_to_others | ref | index_person_redirect_relationships_on_child_id, index_person_redirect_relationships_on_stop_person | index_person_redirect_relationships_on_child_id | 5 | knolcano_development.people.id
| 2 | | | 1 | SEMPLICE | r_p_check | ref | index_person_organization_relationships_on_person_id, index_person_organization_relationships_on_stop_person | index_person_organization_relationships_on_person_id | 5 | knolcano_development.r_from_others.child_id
| 1 | | | 1 | SEMPLICE | r_o_check | ref | index_organization_redirect_relationships_on_child_id, index_organization_redirect_relationships_on_stop_organization | index_organization_redirect_relationships_on_child_id | 5 | knolcano_development.person_organization_relationships.organization_id | 1 | | | 1 | SEMPLICE | rr_p_check | ref | index_person_organization_relationships_on_person_id, index_person_organization_relationships_on_stop_person | index_person_organization_relationships_on_person_id | 5 | knolcano_development.r_from_others.child_id
| 1 | | | 1 | SEMPLICE | rr_o_check | ref | index_organization_redirect_relationships_on_child_id, index_organization_redirect_relationships_on_stop_organization | index_organization_redirect_relationships_on_child_id | 5 | knolcano_development.rr_p_check.organization_id
| 1 | Usando dove | + ---- + ------------- + ----------------------------- ------ + -------- + ---------------------------------- -------------------------------------------------- ---------------------------------- + --------------- ---------------------------------------- + --------- + ------------------------------------------------- ----------------------- + ------ + ------------------- -------------- + 9 righe nel set (0,00 secondi)

Ma quando ho eseguito la query ci sono voluti 0,14 sec. È un lungo periodo di tempo? Sto cercando di capire se ho delle buone domande prima di implementare memcached.

+4

La query effettiva e l'output EXPLAIN sarebbero utili bit di informazioni. –

+0

Sono d'accordo con @JoeStefanelli. Mostraci la query + risultato di 'EXPLAIN'. – Tadeck

risposta

3

Ci potrebbero essere diversi motivi per questo. Scarse prestazioni delle query, indici non validi e così via. Spiegare, interrogare e probabilmente anche creare istruzioni sulla tabella per le tabelle in questione farebbero molto per aiutare a trovare una risposta.

La maggior parte delle volte in cui vedo questo tipo di cose, tuttavia, si tratta di indici scadenti.

7

Quindi molti JOIN possono essere una pessima idea, ma è necessario mostrare prima la query.

Prima di tutto, gli indici sono necessari per velocizzare la query. Se non ne hai, probabilmente dovresti crearne uno (dipende dalla query che esegui).

E se si eseguono più LEFT JOIN, è possibile (probabilmente) separarli in query diverse e questo dovrebbe rendere l'applicazione molto più veloce.

È possibile fare riferimento allo MySQL's documentation on optimization, nello specifico LEFT JOIN optimization e optimization using indexes. Questo potrebbe darti ulteriori dettagli.

+0

Buona risposta, voglio solo sottolineare che il cattivo uso degli indici è la causa più probabile di cattive prestazioni in questi tipi di scenari. –