MySQL: яке з'єднання краще між лівим зовнішнім і внутрішнім з'єднанням


11

Яке з'єднання краще, якщо всі вони дають однаковий результат? Наприклад, у мене є дві таблиці employees(emp_id,name, address, designation, age, sex)і work_log(emp_id,date,hours_wored). Отримати якісь конкретні результати і те, inner joinі left joinдає той же результат. Але у мене все ще є сумніви, які не обмежуються лише цим питанням.

  • яке об'єднання є більш ефективним, що слід віддати перевагу у випадку однакових значень результату?
  • Які ще фактори, які слід враховувати під час подання заявки на приєднання?
  • Чи існує якийсь зв’язок між внутрішнім з'єднанням та перехресним з'єднанням?

Відповіді:


15

Не існує "кращого" чи "гіршого" типу приєднання. Вони мають різний зміст, і їх потрібно використовувати залежно від цього.

У вашому випадку, ви , ймовірно , не мають співробітників з не work_log (ні однієї рядки в цій таблиці), так LEFT JOINі JOINбудуть еквівалентні в результатах. Однак якби у вас було таке (новий працівник без зареєстрованого work_log), Wold опустить JOINцього працівника, тоді як лівий приєднаний (чия перша таблиця є працівники) показував би їх усі, і нулі на полях з work_log, якщо вони є не відповідають.

Візуальне пояснення типів JOIN

Знову ж таки, продуктивність є другорядною справою щодо правильності запиту. Деякі люди кажуть, що не слід використовувати LEFT JOINs. Це правда, що LEFT JOIN змушує оптимізатора виконувати запит в одному конкретному порядку, запобігаючи деяким оптимізаціям (упорядкування таблиці) в деяких випадках. Ось один приклад . Але не слід вибирати один над іншим, якщо правильність / сенс є жертвою, оскільки ВНУТРІШНЯ ПРИЄДНАННЯ не властиво гірше. Решта звичайних оптимізацій застосовуються як завжди.

Підсумовуючи це, не використовуйте, LEFT JOINякщо ви дійсно маєте на увазі INNER JOIN.

В MySQL CROSS JOIN, INNER JOINі JOINодні і ті ж. У стандартному, і семантичному відношенні, а CROSS JOINє застереження INNER JOINбез ON, тому ви отримуєте кожну комбінацію рядків між таблицями.

У вас є приклади всіх семантичних типів приєднання у Вікіпедії . На практиці в MySQL ми прагнемо лише писати JOINі LEFT JOIN.


1
Gr8 пояснення @jynus. Пощастило, що я отримав відповідь на моє запитання лише від вас.
Ursitesion

1 відповідна графіка краще 1000 слів. Ви встигли?
Fr0zenFyr

Ні, я цього не робив, атрибуція знаходиться внизу зображення codeproject.com/Articles/33052/… - Хоча використання діаграм Венна для представлення приєднань стільки ж, скільки і його алгебраїчна формалізація: en.wikipedia.org/wiki/Relational_algebra
jynus

Я почав набір коментарів, потім зрозумів, що все зводиться до цього - це залежить від вашого запиту. +1 від мене!
iheanyi


0

Яке поєднання є більш ефективним, якщо всі вони дають однаковий результат?

На додаток до попередньої відповіді, наскільки я знаю, MySQL оптимізований для того, щоб мати однакову продуктивність.

З хорошими індексами, наприклад, JOINvs LEFT JOIN+ WHEREпункт про фільтрування, буде те саме. Оптимізація проти Human Reading має сенс у великих запитах із великою кількістю приєднань.

Використання хороших індексів та кешу важливіше.

Хороше пояснення процесу оптимізації ви можете прочитати тут:

Процес оптимізації запитів : Запит часто може виконуватися різними способами і давати однаковий результат. Завдання оптимізатора - знайти найкращий варіант.


0

MySql 5.7 8 vCPU, 52 ГБ оперативної пам’яті, це не те саме

Наступний запит займає ~ 30 секунд, не знаю, чому

Таблиця транзакцій містить 24 257 155 записів

Таблиця активності містить 18 603 665 записів

Таблиця закупівель містить 13 911 705 записів

Усі необхідні індекси є на місці

SELECT
    `trx`.`transaction_pk`,
    `trx`.`created`,
    `trx`.`updated`,
    `p`.`amount`,
    `trxst`.`name`,
    COALESCE ( a.units, 0 ) AS units
FROM
    `transaction` AS `trx`
    INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`
    left JOIN `activity` AS `a` ON `a`.`transaction_fk` = `trx`.`transaction_pk`
    LEFT JOIN `purchases` AS `p` ON `p`.`transaction_fk` = `trx`.`transaction_pk` 
WHERE
    `trx`.`entity_fk` IN ( 1234) 
    AND `trx`.`transaction_sub_type_fk` IN (
    2, 4, 5, 15, 16, 33, 37, 38, 85, 86, 87, 88, 102, 103 
    ) 
ORDER BY
    `trx`.`transaction_pk` DESC LIMIT 100 OFFSET 0;

Після заміни наступного рядка:

INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

з лівим приєднанням

LEFT JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

той же запит займає ~ 0,046 с

Поясніть раніше:

1   SIMPLE  trxst       ALL PRIMARY             101 37.62   Using where; Using temporary; Using filesort
1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   transaction_sub_type_fk 4   trxst.transaction_sub_type_pk   2548    0.36    Using where
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 

Поясніть після:

1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   entity_fk   4   const   81474   83.65   Using where
1   SIMPLE  trxst       eq_ref  PRIMARY PRIMARY 4   trx.transaction_sub_type_fk 1   100 
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.