Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Czy powinienem użyć funkcji JOIN, czy uruchomić kilka zapytań w strukturze pętli?

Żadne z dwóch proponowanych rozwiązań nie jest prawdopodobnie optymalne, ALE rozwiązanie 1 jest NIE PRZEWIDYWALNE, a tym samym Z WŁAŚCIWEJ WŁAŚCIWEJ!

Jedną z pierwszych rzeczy, których uczysz się podczas pracy z dużymi bazami danych, jest to, że „najlepszy sposób” wykonania zapytania często zależy od czynników (zwanych metadanymi) w bazie danych:

  • Ile jest wierszy.
  • Ile tabel wykonujesz zapytania.
  • Rozmiar każdego wiersza.

Z tego powodu jest mało prawdopodobne, aby istniało rozwiązanie Twojego problemu. Twoja baza danych nie jest taka sama jak moja, będziesz musiał przetestować różne optymalizacje, jeśli potrzebujesz najlepszej dostępnej wydajności.

Prawdopodobnie zauważysz, że stosowanie i budowanie poprawnych indeksów (i zrozumienie natywnej implementacji indeksów w MySQL) w Twojej bazie danych robi dla Ciebie dużo więcej.

Istnieje kilka złotych zasad dotyczących zapytań, które rzadko powinny być łamane:

  • Nie rób ich w strukturach pętli . Choć często bywa kuszące, narzut związany z utworzeniem połączenia, wykonaniem zapytania i otrzymaniem odpowiedzi jest wysoki.
  • Unikaj SELECT * chyba że jest to potrzebne . Wybranie większej liczby kolumn znacznie zwiększy obciążenie Twoich operacji SQL.
  • Poznaj swoje indeksy . Użyj EXPLAIN funkcja, dzięki której możesz zobaczyć, które indeksy są używane, zoptymalizuj swoje zapytania, aby wykorzystać to, co jest dostępne i twórz nowe.

Z tego powodu z tych dwóch wybrałbym drugie zapytanie (zastępując SELECT * tylko z tymi kolumnami, które chcesz), ale prawdopodobnie istnieją lepsze sposoby ustrukturyzowania zapytania, jeśli masz czas na optymalizację.

Jednak prędkość NIE weź pod uwagę tylko to, istnieje WIELKI powód, aby nie używać jednej z sugestii:

PRZEWIDYWALNOŚĆ:dlaczego blokady odczytu są czymś dobrym

Jedna z innych odpowiedzi sugeruje, że blokowanie tabeli przez długi czas jest złą rzeczą i dlatego rozwiązanie z wieloma zapytaniami jest dobre.

Twierdzę, że to nie może być dalsze od prawdy . W rzeczywistości twierdzę, że w wielu przypadkach przewidywalność uruchomienia pojedynczego blokującego SELECT zapytanie jest większym argumentem ZA uruchomieniem tego zapytania niż korzyści z optymalizacji i szybkości.

Przede wszystkim, gdy uruchamiamy SELECT (tylko do odczytu) zapytanie do bazy danych MyISAM lub InnoDB (systemy domyślne dla MySQL), dzieje się tak, że tabela jest zablokowana do odczytu. Zapobiega to wykonywaniu jakichkolwiek operacji WRITE na tabeli, dopóki blokada odczytu nie zostanie zniesiona (albo nasz SELECT zapytanie kończy się lub kończy się niepowodzeniem). Inne SELECT nie ma to wpływu na zapytania, więc jeśli korzystasz z aplikacji wielowątkowej, będą one nadal działać.

To opóźnienie jest DOBRE. Dlaczego możesz zapytać? Relacyjna integralność danych.

Weźmy przykład:przeprowadzamy operację, aby uzyskać listę przedmiotów znajdujących się obecnie w ekwipunku grupy użytkowników w grze, więc wykonujemy to połączenie:

SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;

Co się stanie, jeśli podczas tej operacji zapytania użytkownik wymieni przedmiot z innym użytkownikiem? Używając tego zapytania, widzimy stan gry taki, jaki był w chwili rozpoczęcia zapytania:przedmiot istnieje raz, w ekwipunku użytkownika, który miał go przed uruchomieniem zapytania.

Ale co się stanie, jeśli uruchomimy go w pętli?

W zależności od tego, czy użytkownik handlował nim przed, czy po zapoznaniu się z jego danymi oraz w jakiej kolejności odczytujemy ekwipunek dwóch graczy, istnieją cztery możliwości:

  1. Przedmiot może zostać wyświetlony w ekwipunku pierwszego użytkownika (skanuj użytkownika B -> skanuj użytkownika A -> przedmiot będący przedmiotem wymiany LUB skanuj użytkownika B -> skanuj użytkownika A -> przedmiot będący przedmiotem wymiany).
  2. Przedmiot może zostać wyświetlony w ekwipunku drugiego użytkownika (przedmiot będący przedmiotem wymiany -> skan użytkownika A -> skan użytkownika B LUB przedmiot będący przedmiotem wymiany -> skan użytkownika B -> skan użytkownika A).
  3. Element może być pokazany w obu inwentarze (skanuj użytkownika A -> przedmiot będący przedmiotem handlu -> skanuj użytkownika B).
  4. Element nie mógł być wyświetlany w ani ekwipunku użytkownika (skanuj użytkownika B -> przedmiot będący przedmiotem handlu -> skanuj użytkownika A).

Oznacza to, że nie bylibyśmy w stanie przewidzieć wyników zapytania ani zapewnić integralności relacyjnej .

Jeśli planujesz dać 5000 $ facetowi o ID 1000000 we wtorek o północy, mam nadzieję, że masz pod ręką 10 000 $. Jeśli Twój program opiera się na unikalnych elementach, które są unikatowe podczas wykonywania zrzutów, prawdopodobnie zgłosisz wyjątek przy tego rodzaju zapytaniu.

Blokowanie jest dobre, ponieważ zwiększa przewidywalność i chroni uczciwość wyników.

Uwaga:możesz wymusić zablokowanie pętli za pomocą transakcji , ale będzie nadal bądź wolniejszy.

Och, na koniec UŻYJ PRZYGOTOWANYCH OŚWIADCZEŃ!

Powinieneś nigdy mieć oświadczenie, które wygląda tak:

mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);

mysqli ma obsługę przygotowanych oświadczeń . Przeczytaj o nich i korzystaj z nich, pomogą Ci uniknąć coś strasznego dzieje się w Twojej bazie danych .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ostrzeżenie:mysql_result() [function.mysql-result]:Nie można przeskoczyć do wiersza 0 w indeksie wyników MySQL 5 w profile.php w wierszu 11

  2. budowanie aplikacji opartej na rolach

  3. Jak zachować dane UTF8mb4 za pomocą mysqldump?

  4. dostępność pokoju zapytań mysql

  5. Jak opróżnić wszystkie wiersze ze wszystkich tabel w mysql (w sql)