Улучшение производительности с LEFT JOIN - PullRequest
5 голосов
/ 27 октября 2011

У меня есть запрос MySQL, который имеет 5 или 6 левых соединений.Как и ожидалось, это довольно медленно.Учитывая, что я ожидаю только ~ 100 результатов, возможно, для меня было бы больше смысла запускать множество отдельных SQL-запросов и объединять их вручную.Я предполагаю, что это занимает много времени из-за огромной таблицы, которая создается с несколькими левыми соединениями.Это верно?

Я делаю это в Rails 3. Я знаю, что создание активных записей стоит дорого, но я полагаю, что это может быть быстрее, чем иметь так много LEFT JOINS.Я очень мало знаю о том, как база данных работает под капотом.Был бы очень признателен за любые идеи.


Редактировать: Вот фактические схемы запросов и таблиц

Запрос

SELECT people. * FROM people LEFT JOIN person_organization_relationships ONperson_organization_relationships .person_id = people .id AND person_organization_relationships .stop_person имеет значение NULL LEFT JOIN person_redirect_relationships AS r_from_others ON r_from_others.parent_id = people .id AND r_from_others.stop_person IS NULL LEFT JOIN person_redirect_relationships AS r_to_sr_to_others.child_id = people .id AND r_to_others.stop_person IS NULL СЛЕДУЕТ ПРИСОЕДИНЯТЬСЯ person_organization_relationships AS r_p_check ON r_p_check.person_id = r_from_others.child_id AND r_p_check.stop_person IS NULL LEFT JOIN_0__________ * organization_redirect_relationships* .organization_id AND r_o_check.stop_organization IS NULL ЛЕВАЯ ПРИСОЕДИНЯТЬСЯ person_organization_relationships КАК rr_p_check ВКЛ rr_p_check.person_id = r_from_others.child_id И rr_p_check.stop_person IS НУЛЕВОЙ ЛЕВЫЙ РЕЙТИНГNULL WHERE (((* person_organization_relationships .organization_id = 1 OR r_o_check.parent_id = 1) И r_to_others.parent_id IS NULL) ИЛИ (r_p_check.organization_id = 1 ИЛИ 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"

Этот запрос не дал результатов.

+ ---- + ------------- + ----------------------------------- + -------- + ---------------------------------------------------------------------------------------------------------------------- + ------------------------------------------------------- + --------- + ------------------------------------------------------------------------ + ------ + --------------------------------- + |id |select_type |стол |тип |возможные_ключи
|ключ |key_len |ref
|строки |Extra |+ ---- + ------------- + ----------------------------------- + -------- + ---------------------------------------------------------------------------------------------------------------------- + ------------------------------------------------------- + --------- +------------------------------------------------------------------------ + ------ + --------------------------------- + |1 |ПРОСТО |person_details |ВСЕ |index_person_details_on_current_p_id
|NULL |NULL |NULL
|4938 |Используя временные;Использование сортировки файлов ||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.

Ответы [ 2 ]

7 голосов
/ 27 октября 2011

Очень много JOIN может быть очень плохой идеей, но сначала вы должны показать свой запрос.

Прежде всего, индексы необходимы для ускорения запроса.Если у вас их нет, вам, вероятно, следует создать их (в зависимости от того, какой запрос вы выполняете).

А если вы выполняете несколько LEFT JOIN, вы можете (вероятно) разделить их на разные запросы, и это должно сделатьприложение работает намного быстрее.

Вы можете обратиться к документации MySQL по оптимизации , в частности LEFT JOIN оптимизация и оптимизация с использованием индексов .Это может дать вам дополнительную информацию.

3 голосов
/ 27 октября 2011

Для этого может быть несколько причин.Низкая производительность запросов, плохие индексы и т. Д.Объяснение, запрос и, возможно, даже создание операторов таблиц для рассматриваемых таблиц очень помогли бы прийти к ответу.

Хотя в большинстве случаев я вижу подобные вещи,это вопрос плохих показателей.

...