2011-10-26 18 views
5

Tengo una consulta de MySQL que tiene 5 o 6 UNIONES IZQUIERDAS. Como se esperaba, esto es bastante lento. Teniendo en cuenta que solo estoy esperando ~ 100 resultados, ¿podría tener más sentido para mí ejecutar muchas consultas SQL separadas y unirlas manualmente? Supongo que tarda mucho tiempo debido a la gran tabla que se crea con varias combinaciones a la izquierda. ¿Está bien?Mejore el rendimiento con LEFT JOIN

Estoy haciendo esto en Rails 3. Sé que la creación de registros activos es costosa, pero supongo que puede ser más rápido que tener tantas IZQUIERDAS. Sé muy poco sobre cómo funciona la base de datos bajo el capó. Realmente apreciaría cualquier idea.


Editar: Aquí está la consulta y la tabla de esquemas reales

de consulta

SELECT * FROM peoplepeople LEFT JOIN person_organization_relationships EN person_organization_relationships .person_id = people .ID Y person_organization_relationships.. stop_person IS NULL LEFT JOIN person_redirect_relationships AS r_from_others EN r_from_others.parent_id = people .ID Y r_from_others.stop_person ES NULL LEFT JOIN person_redirect_relationships AS r_to_others EN r_to_others.child_id = people .ID Y r_to_others.stop_person IS NULL LEFT JOIN person_organization_relationships AS r_p_check EN r_p_check.person_id = r_from_others. child_id Y r_p_check.stop_person se deja NULL JOIN organization_redirect_relationships AS r_o_check EN r_o_check.child_id = person_organization_relationships .organization_id Y r_o_check.stop_organization es unirse a LEFT NULL person_organization_relationships AS rr_p_check EN rr_p_check.person_id = r_from_others.child_i D y rr_p_check.stop_person se deja NULL JOIN organization_redirect_relationships AS rr_o_check EN rr_p_check.organization_id = rr_o_check.child_id Y rr_o_check.stop_organization IS NULL DONDE (((person_organization_relationships .organization_id = 1 OR r_o_check.parent_id = 1) y r_to_others .parent_id IS NULL) OR (r_p_check.organization_id = 1 OR rr_o_check.parent_id = 1)) GROUP BY people .id

esquema de tabla:

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" 

Esta consulta no produjo resultados.

+ ---- + ------------- + ------------------------ ----------- + -------- + ----------------------------- -------------------------------------------------- --------------------------------------- + ---------- --------------------------------------------- + ---- ----- + -------------------------------------------- ---------------------------- + ------ + -------------- ------------------- + | id | select_type | mesa | tipo | possible_keys
| clave | key_len | ref
| filas | Extra | + ---- + ------------- + ----------------------------- ------ + -------- + ---------------------------------- -------------------------------------------------- ---------------------------------- + --------------- ---------------------------------------- + --------- + ------------------------------------------------- ----------------------- + ------ + ------------------- -------------- + | 1 | SIMPLE | detalles de la persona | TODO | index_person_details_on_current_p_id
| NULL | NULL | NULL
| 4938 | Usando temporal; Usando filesort | | 1 | SIMPLE | gente | eq_ref | PRIMARIO
| PRIMARIO | 4 | knolcano_development.person_details.current_p_id
| 1 | | | 1 | SIMPLE | 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 | SIMPLE | 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 | SIMPLE | 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 | SIMPLE | 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 | SIMPLE | 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 | SIMPLE | 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 | SIMPLE | 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 donde | + ---- + ------------- + ----------------------------- ------ + -------- + ---------------------------------- -------------------------------------------------- ---------------------------------- + --------------- ---------------------------------------- + --------- + ------------------------------------------------- ----------------------- + ------ + ------------------- -------------- + 9 filas en el conjunto (0,00 segundos)

Pero cuando ejecuté la consulta tomó 0.14 segundos. ¿Es eso un largo período de tiempo? Estoy tratando de averiguar si tengo buenas consultas antes de implementar Memcached.

+4

La consulta real y la salida EXPLAIN serían fragmentos de información útiles. –

+0

Estoy de acuerdo con @JoeStefanelli. Muéstranos la consulta + resultado de 'EXPLAIN'. – Tadeck

Respuesta

3

Puede haber una serie de razones para esto. Rendimiento de consulta pobre, índices incorrectos, etc. Las instrucciones de explicación, consulta e incluso creación de tabla para las tablas en cuestión contribuirían en gran medida a ayudar a encontrar una respuesta.

La mayoría de las veces cuando veo este tipo de cosas, sin embargo, es una cuestión de índices pobres.

7

Muchos JOINs pueden ser una muy mala idea, pero primero debe mostrar su consulta.

En primer lugar, se requieren índices para acelerar la consulta. Si no tiene ninguno, probablemente debería crear algunos (según la consulta que realice).

Y si haces varias UNIONES IZQUIERDAS, entonces podrías (probablemente) separarlas en diferentes consultas y esto debería hacer que la aplicación funcione mucho más rápido.

Puede consultar el MySQL's documentation on optimization, específicamente LEFT JOIN optimization y optimization using indexes. Esto puede darle detalles adicionales.

+0

Buena respuesta, solo quiero enfatizar que el mal uso de los índices es la causa más probable del mal desempeño en este tipo de escenarios. –