Справжнє запитання: Чи мають ці записи стосунки один до одного або стосунки один до багатьох ?
Відповідь TLDR:
Якщо один на один, використовуйте JOIN
вислів.
Якщо один-багато-багато, використовуйте один (або багато) SELECT
операторів з оптимізацією коду на стороні сервера.
Чому і як використовувати SELECT для оптимізації
SELECT
'ing (з декількома запитами замість об'єднання) для великої групи записів на основі взаємозв'язку один до багатьох виробляє оптимальну ефективність, оскільки JOIN
' ing має проблему експоненціальної витоку пам'яті. Візьміть усі дані, а потім скористайтеся мовою скриптів на стороні сервера, щоб впорядкувати їх:
SELECT * FROM Address WHERE Personid IN(1,2,3);
Результати:
Address.id : 1 // First person and their address
Address.Personid : 1
Address.City : "Boston"
Address.id : 2 // First person's second address
Address.Personid : 1
Address.City : "New York"
Address.id : 3 // Second person's address
Address.Personid : 2
Address.City : "Barcelona"
Ось, я отримую всі записи, в одному виділеному заяві. Це краще, ніж те JOIN
, що отримувало б невелику групу цих записів, по одному, як підкомпонент іншого запиту. Потім я розбираю його з кодом на стороні сервера, який виглядає приблизно так ...
<?php
foreach($addresses as $address) {
$persons[$address['Personid']]->Address[] = $address;
}
?>
Коли не використовувати JOIN для оптимізації
JOIN
'велика група записів, що базується на взаємозв'язку один на один з одним записом, забезпечує оптимальну ефективність порівняно з декількома SELECT
висловлюваннями, одна за одною, які просто отримують наступний тип запису.
Але JOIN
це неефективно при отриманні записів, які мають стосунки один до багатьох.
Приклад: Блоги в базі даних містять 3 цікаві таблиці, Blogpost, тег та коментар.
SELECT * from BlogPost
LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id
LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;
Якщо є 1 блог, 2 теги та 2 коментарі, ви отримаєте такі результати:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,
Зауважте, як дублюється кожен запис. Гаразд, так, 2 коментарі та 2 теги - це 4 ряди. Що робити, якщо у нас є 4 коментарі та 4 теги? Ви не отримуєте 8 рядків - ви отримуєте 16 рядків:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag1, comment3,
Row4: tag1, comment4,
Row5: tag2, comment1,
Row6: tag2, comment2,
Row7: tag2, comment3,
Row8: tag2, comment4,
Row9: tag3, comment1,
Row10: tag3, comment2,
Row11: tag3, comment3,
Row12: tag3, comment4,
Row13: tag4, comment1,
Row14: tag4, comment2,
Row15: tag4, comment3,
Row16: tag4, comment4,
Додайте більше таблиць, більше записів і т. Д., І проблема швидко розгорнеться до сотень рядків, які наповнені переважно зайвими даними.
Скільки коштують ці дублікати? Пам'ять (на SQL-сервері та код, який намагається видалити дублікати) та мережеві ресурси (між SQL-сервером та сервером коду).
Джерело: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/uk/wb-relationship-tools.html