使用LEFT JOIN提高性能

Cyr*_*rus 5 mysql activerecord left-join ruby-on-rails-3

我有一个有5或6个LEFT JOINS的mysql查询.正如预期的那样,这很慢.考虑到我只期望大约100个结果,我可能更有意义的是运行大量单独的SQL查询并手动将它们拼接在一起.我猜这需要很长时间,因为使用多个左连接创建的巨大表.是对的吗?

我在Rails 3中这样做.我知道创建活动记录是昂贵的,但我认为它可能比拥有这么多LEFT JOINS更快.我对数据库的工作原理知之甚少.非常感谢任何见解.


编辑:这是实际的查询和表模式

询问

SELECT people.*FROM peopleLEFT JOIN person_organization_relationshipsON person_organization_relationships.person_id = people.id AND person_organization_relationships.stop_person IS NULL LEFT JOIN person_redirect_relationshipsas r_from_others ON r_from_others.parent_id = people.id AND r_from_others.stop_person IS NULL LEFT JOIN person_redirect_relationshipsas r_to_others ON r_to_others.child_id = people.id AND r_to_others.stop_person IS NULL LEFT JOIN person_organization_relationshipsAS r_p_check ON r_p_check.person_id = r_from_others.child_id AND r_p_check.stop_person IS NULL LEFT JOIN organization_redirect_relationshipsas r_o_check ON r_o_check.child_id = person_organization_relationships.organization_id AND r_o_check.stop_organization IS NULL LEFT JOIN person_organization_relationshipsAS rr_p_check ON rr_p_check.person_id = r_from_others.child_id AND rr_p_check .stop_person IS NULL LEFT JOIN organization_redirect_relationshipsAS rr_o_check ON rr_p_check.organization_id = rr_o_check.child_id AND rr_o_check.stop_organization IS NULL WHERE(((. person_organization_relationshipsorganization_id = 1 OR r_o_check.parent_id = 1)AND 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

表模式:

  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"
Run Code Online (Sandbox Code Playgroud)

此查询未产生任何结果.

+ ---- + ------------- + ------------------------------ ----- + -------- + ----------------------------------- -------------------------------------------------- --------------------------------- + ---------------- --------------------------------------- + --------- + -------------------------------------------------- ---------------------- + ------ + -------------------- ------------- + | id | select_type | 表| 类型| possible_keys
| 关键| key_len | ref
| 行| 额外的| + ---- + ------------- + ------------------------------ ----- + -------- + ----------------------------------- -------------------------------------------------- --------------------------------- + ---------------- --------------------------------------- + --------- + -------------------------------------------------- ---------------------- + ------ + -------------------- ------------- + | 1 | 简单| person_details | 所有| index_person_details_on_current_p_id
| NULL | NULL | NULL
| 4938 | 使用临时; 使用filesort | | 1 | 简单| 人民| eq_ref | 主要
| 主要| 4 | knolcano_development.person_details.current_p_id
| 1 | | | 1 | 简单| 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 | 简单| 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 | 简单| 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 | 简单| 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 | 简单| 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 | 简单| 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 | 简单| 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 | 使用何处| + ---- + ------------- + ------------------------------ ----- + -------- + ----------------------------------- -------------------------------------------------- --------------------------------- + ---------------- --------------------------------------- + --------- + -------------------------------------------------- ---------------------- + ------ + -------------------- ------------- + 9行(0.00秒)

但是当我运行查询时,花了0.14秒.那是很长一段时间吗?我想在实现memcached之前弄清楚我是否有好的查询.

Tad*_*eck 7

这么多JOIN可能是一个非常糟糕的主意,但你应该先显示你的查询.

首先,需要索引来加速查询.如果你没有,你可能应该创建一些(取决于你执行的查询).

如果你做了多个LEFT JOIN,那么你可以(可能)将它们分成不同的查询,这应该可以使应用程序更快地运行.

您可以参考MySQL关于优化的文档,特别是使用索引进行LEFT JOIN优化优化.这可能会为您提供更多细节.


Jer*_*con 3

造成这种情况的原因可能有很多。查询性能差、索引不好等等。对有问题的表进行解释、查询,甚至可能创建表语句将有助于获得答案。

不过,大多数时候,当我看到这种事情时,都是索引不佳的问题。