Prawdziwe pytanie brzmi: czy te rekordy mają relację jeden do jednego czy jeden do wielu ?
Odpowiedź TLDR:
Jeśli masz jeden do jednego, użyj pliku JOIN
instrukcji.
Jeśli jeden do wielu, użyj jednej (lub wielu) SELECT
instrukcji z optymalizacją kodu po stronie serwera.
Dlaczego i jak używać SELECT do optymalizacji
SELECT
Praca (z wieloma zapytaniami zamiast łączenia) na dużej grupie rekordów w oparciu o relację jeden do wielu zapewnia optymalną wydajność, ponieważ JOIN
wiąże się z wykładniczym problemem wycieku pamięci. Pobierz wszystkie dane, a następnie posortuj je za pomocą języka skryptowego po stronie serwera:
SELECT * FROM Address WHERE Personid IN(1,2,3);
Wyniki:
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"
Tutaj otrzymuję wszystkie rekordy w jednej wybranej instrukcji. Jest to lepsze niż JOIN
pobieranie niewielkiej grupy tych rekordów, pojedynczo, jako podkomponentu innego zapytania. Następnie analizuję go za pomocą kodu po stronie serwera, który wygląda mniej więcej tak ...
<?php
foreach($addresses as $address) {
$persons[$address['Personid']]->Address[] = $address;
}
?>
Kiedy nie używać JOIN do optymalizacji
JOIN
Tworzenie dużej grupy rekordów w oparciu o relację jeden do jednego z jednym rekordem zapewnia optymalną wydajność w porównaniu z wieloma SELECT
instrukcjami, jeden po drugim, które po prostu pobierają następny typ rekordu.
Ale JOIN
jest nieefektywny w przypadku uzyskiwania rekordów w relacji jeden do wielu.
Przykład: Baza danych Blogi zawiera 3 interesujące tabele: Post na blogu, Znacznik i Komentarz.
SELECT * from BlogPost
LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id
LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;
Jeśli jest 1 post na blogu, 2 tagi i 2 komentarze, otrzymasz wyniki takie jak:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,
Zwróć uwagę, jak każdy rekord jest zduplikowany. OK, więc 2 komentarze i 2 tagi to 4 rzędy. A co jeśli mamy 4 komentarze i 4 tagi? Nie dostajesz 8 rzędów - dostajesz 16 rzędów:
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,
Dodaj więcej tabel, więcej rekordów itp., A problem szybko rozwinie się do setek wierszy, które są pełne w większości nadmiarowych danych.
Ile kosztują te duplikaty? Pamięć (na serwerze SQL i kod, który próbuje usunąć duplikaty) i zasoby sieciowe (między serwerem SQL a serwerem kodu).
Źródło: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html