2014-03-04 3 views
0

Я пытаюсь выяснить более эффективный способ написания запроса, который использует моя компания. В настоящее время мы используем LEFT JOINs, но я чувствую, что это может быть плохой подход к этому.Оптимизация запроса с помощью JOINs

Как вы относитесь к этому? Я пытаюсь ознакомиться с EXISTS и CROSS APPLY. Возможно, это ситуация, когда я должен использовать эти типы утверждений.

SELECT p.people_id , 
     p.date_created , 
     p.last_name , 
     p.first_name , 
     p.middle_name , 
     p.known_as , 
     p.ssn , 
     p.home_phone , 
     p.work_mobile , 
     p.other_phone , 
     p.display_email , 
     s.source , 
     ISNULL(p.address_1, '') AS address_1 , 
     ISNULL(p.address_2, '') AS address_2 , 
     p.city , 
     p.state , 
     p.zip_code , 
     pec.emergency_name , 
     pec.work_phone , 
     pec.emergency_relationship , 
     jc.job_category , 
     et.education_type , 
     pp.part_time_only , 
     pp.perm_job , 
     pp.temp_job , 
     p.applied_online , 
     p.owner_division_id , 
     p.role_id , 
     p.older_18 , 
     p.disclaimer , 
     SUBSTRING(p.ssn, 6, 4) AS L4_ssn , 
     pp.custom_code_4 AS job_title , 
     p.external_id , 
     p.last4 , 
     p.resume_category , 
     rc.resume_category_description , 
     p.home_phone_perm , 
     p.work_mobile_perm 
FROM people p 
     LEFT OUTER JOIN lkp_resume_category rc ON p.resume_category = rc.resume_category_id 
     LEFT OUTER JOIN people_profile pp ON pp.people_id = p.people_id 
     LEFT OUTER JOIN companies_job_titles cjt ON cjt.job_title_id = pp.job_title_1 
     LEFT OUTER JOIN lkp_job_categories jc ON jc.job_category_id = pp.job_class_id 
     LEFT OUTER JOIN lkp_education_types et ON et.education_type_id = pp.education_id 
     LEFT OUTER JOIN lkp_sources s ON pp.source_id = s.source_id 
     LEFT OUTER JOIN people_emergency_contacts pec ON p.people_id = pec.people_id 
WHERE (p.role_id <= 4) 

Results Plan Diagram

+0

Не похож на «INNER JOINs». Но, глядя на план выполнения, вы должны посмотреть на индексацию своих таблиц. – Magnus

+0

Я неправильно напечатал это. Спасибо, что указали. – HKImpact

ответ

3

Там фактически два отдельных вопроса спрашивают здесь:

  1. Должен ли я использовать ЛЕВАЯ JOIN и?
  2. Как сделать мой запрос более эффективным?

Я отвечу # 2 сначала, потому что я думаю, что это проще. В вашем плане запроса более 70% ваших расходов происходит из таблицы сканирования таблицы «люди». Таким образом, вы можете оптимизировать свои JOINs весь день и не повышать эффективность. Критический вопрос: какой процент ваших «людей» имеет «role_id < = 4»? Если это менее 10%, у вас есть место для оптимизации на основе того, как вы индексируете; если это больше, чем около 70% - то есть, если цель этого запроса состоит в том, чтобы вытащить почти полный список всех в таблице «люди», то вам в значительной степени просто придется заплатить то, что стоит сделать ,

Теперь о вопросе № 1: если следующие выводы о вашей модели данных верны, то ваши ЛЕВЫЕ СОЕДИНЕНИЯ, вероятно, лучший способ сделать то, что вы пытаетесь сделать. Выводы следующие:

  1. Запись «людей» имеет нулевую категорию соответствия; то есть people.resume_category_id может быть NULL или иметь значимое значение. (Если у него могут быть недопустимые значения, не найденные в родительской таблице, тогда у вас есть проблема ссылочной целостности, и вам нужно ограничение внешнего ключа.)
  2. Запись «люди» имеет аварийные контакты от нуля до многих.
  3. В записи «люди» есть профили пользователей «нуль-ко-многим».
  4. А «люди профиль» запись имеет нуля до одного названия работы (как указано выше, с resume_category)
  5. запись
  6. А «люди профиль» имеет ноль к одной категории рабочих мест (как указано выше)
  7. А «люди (как указано выше)
  8. Запись «Профиль людей» имеет источник «от нуля к одному» (как указано выше)
  9. Вы хотите перечислить всех людей независимо от наличия или отсутствия данные в любом из этих других таблиц

Надеюсь, что это поможет, и все б стандартное восточное время.

--- EDIT ---

Эй, что-то беспокоит меня об этом ответе, и я только сейчас понял, что это такое. Существует реальная проблема с вашей структурой запроса, но она не связана с использованием LEFT JOIN. Это то, что вы присоединяетесь к двум различным дочерним таблицам сразу, причем обе они имеют одну и ту же родительскую таблицу «люди».В зависимости от того, как ваши данные фактически распределены, это даст вам декартовский продукт в качестве вашего набора результатов. Например, предположим, что у вас есть человек «Боб» с двумя профилями («Работа» и «Домой») и два экстренных контакта («Алиса» и «Кэрол»). Тогда запрос структурирована, как ваша даст:

Person Profile Contact 
------ ------- ------- 
Bob  Work  Alice 
Bob  Home  Alice 
Bob  Work  Carol 
Bob  Home  Carol 

Если отношения, которые структурированы как нуль-ко-многим может, на самом деле, есть несколько дочерних строк, то решение зависит от того, как ваше приложение использует данные , Существуют, однако, два основных возможных подхода:

  1. Отделите каждый нуль-ко-многим JOIN в свой собственный запрос, поэтому у вас будет всего три запроса вместо одного.
  2. Используйте какой-то оператор агрегации, такой как FIRST или MAX (слегка отрывочный, поскольку он может давать непредсказуемые результаты и/или смешивать и сопоставлять поля из разных строк в наборе результатов).

Как примечание стороны, если дочерние таблицы не может иметь несколько дочерних строк, то вы должны обеспечить это, поставив единственное ограничение на «people_id» поля каждого из этих таблиц.

Смежные вопросы