Mysql
 sql >> база данни >  >> RDS >> Mysql

Трябва ли да използвам функция JOIN или да изпълня няколко заявки в структура на цикъл?

Нито едно от двете предложени решения вероятно не е оптимално, НО решение 1 е НЕПРЕДСКАЗИМО и следователно СЪЩНОСТНО НЕДОСТАТОЧНО!

Едно от първите неща, които научавате, когато работите с големи бази данни, е, че „най-добрият начин“ за извършване на заявка често зависи от фактори (наричани мета-данни) в базата данни:

  • Колко реда има.
  • Колко таблици правите заявка.
  • Размерът на всеки ред.

Поради това е малко вероятно да има сребърно решение за вашия проблем. Вашата база данни не е същата като моята, ще трябва да сравните различни оптимизации, ако имате нужда от най-добрата налична производителност.

Вероятно ще откриете, че прилагане и изграждане на правилни индекси (и разбирането на естествената реализация на индекси в MySQL) във вашата база данни прави много повече за вас.

Има някои златни правила със заявките, които рядко трябва да се нарушават:

  • Не ги правете в циклични структури . Колкото и често да е изкушаващо, разходите за създаване на връзка, изпълнение на заявка и получаване на отговор са големи.
  • Избягвайте SELECT * освен ако не е необходимо . Избирането на повече колони значително ще увеличи разходите за вашите SQL операции.
  • Познайте своите индекси . Използвайте EXPLAIN функция, така че да виждате кои индекси се използват, да оптимизирате заявките си, за да използвате наличното, и да създавате нови.

Поради това от двете бих отишъл за втората заявка (заменящ SELECT * само с колоните, които искате), но вероятно има по-добри начини за структуриране на заявката, ако имате време за оптимизиране.

Скоростта обаче трябва да НЕ бъдете единственото ви съображение в това, има ГОЛЯМА причина да не използвате едно предложение:

ПРЕДСКАЗИМОСТЬ:защо заключванията за четене са добро нещо

Един от другите отговори предполага, че заключването на таблицата за дълъг период от време е лошо нещо и че следователно решението с множество заявки е добро.

Бих казал, че това не може да бъде по-далеч от истината . Всъщност бих твърдял, че в много случаи предсказуемостта на изпълнение на едно заключване SELECT query е по-голям аргумент ЗА изпълнението на тази заявка, отколкото предимствата за оптимизация и скорост.

На първо място, когато стартираме SELECT (само за четене) към база данни MyISAM или InnoDB (системи по подразбиране за MySQL), това, което се случва, е, че таблицата е заключена за четене. Това предотвратява извършването на операции WRITE на масата, докато блокирането за четене не бъде предадено (или нашия SELECT заявката е завършена или неуспешна). Друго SELECT заявките не са засегнати, така че ако изпълнявате многонишково приложение, те ще продължат да работят.

Това забавяне е ДОБРО. Защо, може да попитате? Цялост на релационни данни.

Да вземем пример:изпълняваме операция, за да получим списък с елементи, които в момента са в инвентара на група потребители на игра, така че правим това присъединяване:

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

Какво се случва, ако по време на тази операция на заявка потребител изтъргува артикул на друг потребител? Използвайки тази заявка, виждаме състоянието на играта такова, каквото е било, когато сме стартирали заявката:елементът съществува веднъж, в инвентара на потребителя, който го е имал, преди да изпълним заявката.

Но какво ще стане, ако го изпълним в цикъл?

В зависимост от това дали потребителят го е търгувал преди или след като прочетем неговите данни и в какъв ред четем инвентара на двамата играчи, има четири възможности:

  1. Елементът може да бъде показан в инвентара на първия потребител (сканиране на потребител B -> сканиране на потребител A -> търгуван артикул ИЛИ сканиране на потребител B -> сканиране на потребител A -> търгуван артикул).
  2. Елементът може да бъде показан в инвентара на втория потребител (търгуван артикул -> сканиране потребител A -> сканиране потребител B ИЛИ търгуван артикул -> сканиране потребител B -> сканиране потребител A).
  3. Елементът може да се показва в и двете инвентари (сканиране на потребител A -> търгуван артикул -> сканиране на потребител B).
  4. Елементът може да бъде показан в нито едно от двете от инвентара на потребителя (сканиране на потребител B -> търгувани артикули -> сканиране на потребител A).

Това означава, че няма да можем да предвидим резултатите от заявката или да гарантираме релационна цялост .

Ако планирате да дадете $5,000 на човека с артикул ID 1000000 в полунощ във вторник, надявам се, че имате $10k на ръка. Ако вашата програма разчита на това, че уникалните елементи са уникални, когато се правят моментни снимки, вероятно ще предизвикате изключение с този вид заявка.

Заключването е добро, защото повишавапредвидимостта и защитава целота на резултатите.

Забележка:Можете да принудите цикъл да се заключи с транзакция , но щесе бъдете по-бавни.

О, и накрая, ИЗПОЛЗВАЙТЕ ПОДГОТОВЛЕНИ ИЗЯВЛЕНИЯ!

Не трябва никога има изявление, което изглежда така:

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

mysqli има поддръжка за подготвени изявления . Прочетете за тях и ги използвайте, те ще ви помогнат да избегнете нещо ужасно да се случи с вашата база данни .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Актуализиране на колоната с времеви отпечатъци в приложение или база данни?

  2. Импортиране на GeoLite2 на MaxMind в MySQL

  3. Създаване на йерархичен JSON от MySQL резултати и PHP за дърво D3.js?

  4. Арабски символ ??????? на php и mysql

  5. как да използвам mysql с asp.net?