Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Przeszukiwanie kilku baz danych jednocześnie
Forum PHP.pl > Forum > Bazy danych > MySQL
willy
Witam,

Zastanawiam się w jaki sposób można rozwiązać następujący problem.
Strona wyszukuje informacji w 10 niezależnych bazach danych o dużych rozmiarach (powiedzmy kilkadziesiąt tysięcy rekordów do przeszukania). Każda na osobnym serwerze. Zwrócenie wyniku każdej z nich trwa powiedzmy 3~5sek.
Jak łatwo policzyć łącznie się z każdą bazą po kolei, wysłanie zapytania, odczytanie wyniku oraz wyświetlanie go na ekranie użytkownika zajmie 30~50 sek.
W jaki sposób wysłać zapytanie do każdej z baz danych, tak żeby wszystkie serwery MySQL wykonywały swoją pracę jednocześnie, a nie po kolei?
Najlepiej by było, gdyby wyniki były wyświetlane zgodnie z kolejnością ich nadchodzenia (czyli serwer który odpowie najszybciej wyświetlany na górze strony)
Czy da się to zrobić z wykorzystaniem czystego PHP, czy trzeba "zaprząc" do pracy inne języki programowania?

Pozdrawiam
-willy-
thek
Do tego trzeba nawiązać asynchroniczne połączenia z bazami. A to wymusza zastosowanie AJAX i w tę stronę bym ciągnął, bo to wydaje mi się najbardziej sensowne z wszystkich możliwych podejść.
Mchl
Cytat(thek @ 14.12.2009, 21:04:30 ) *
Do tego trzeba nawiązać asynchroniczne połączenia z bazami. A to wymusza zastosowanie AJAX i w tę stronę bym ciągnął, bo to wydaje mi się najbardziej sensowne z wszystkich możliwych podejść.


Nie wymusza. Można przecież wywoływać skrypty potomne ze skryptu głównego (co nie znaczy, że tak będzie prościej czy lepiej winksmiley.jpg )

I jest jeszcze coś takiego:
http://www.php.net/manual/en/mysqli.reap-async-query.php

szukam chętnego, który to rozgryzie winksmiley.jpg

[edit]

Ha... czyli od wersji 5.3 PHP można wykonywać zapytania asynchroniczne przy pomocy mysqli_query z flagą MYSQLI_ASYNC
thek
Zauważ, że nawet w tej funkcji mysqli masz połączenie z jedną bazą, To, że wykonuje się asynchronicznie nie oznacza, że połączenia do kilku baz będą takie same. Musiałoby być jako mysql_link nie konkretna wartość, ale tablica, by działało na kilku możliwych i dodatkowo przy każdym zapytaniu musiałbyś ustawiać jaką bazę by obsługiwało w danym wypadku smile.gif Oczywiście podanie tylko 1 bazy mogło by być wywoływaniem mysqli_query w sposób typowy, bez dodatkowego parametru smile.gif

Możliwość z wywoływaniem skryptów potomnych jest, ale zauważ, że późniejsze "zsynchronizowanie wyników" przez nie zwróconych to mógłby być horror nie do przejścia dla większości. W AJAXie jest to jednak możliwe przy sensownie złożonej funkcji w Success bazującej na DOM smile.gif
Mchl
Popełniłem taki test:

  1. <?php
  2.  
  3. $mysqli1 = new mysqli('localhost','root','','test');
  4. $mysqli2 = new mysqli('localhost','root','','test');
  5. $mysqli3 = new mysqli('localhost','root','','test');
  6. $mysqli4 = new mysqli('localhost','root','','test');
  7.  
  8.  
  9. $query = "SELECT SQL_NO_CACHE COUNT(*) AS cnt FROM t9";
  10.  
  11. $tStart = microtime(true);
  12. $result1 = $mysqli1->query($query);
  13. $result2 = $mysqli2->query($query);
  14.  
  15. $row1 = $result1->fetch_assoc();
  16. $row2 = $result2->fetch_assoc();
  17. $tEnd = microtime(true);
  18.  
  19. $tElapsed = $tEnd - $tStart;
  20.  
  21. echo '----------------------------'.PHP_EOL;
  22. echo 'Zapytania po kolei'.PHP_EOL;
  23. echo 'Wynik 1. zapytania: '.$row1['cnt'].PHP_EOL;
  24. echo 'Wynik 2. zapytania: '.$row2['cnt'].PHP_EOL;
  25. echo 'Łączny czas: '.$tElapsed.PHP_EOL;
  26. echo '----------------------------'.PHP_EOL;
  27.  
  28. $row1 = $row2 = $row3 = $row4 = null;
  29.  
  30.  
  31. $tStart = microtime(true);
  32. $mysqli1->query($query,MYSQLI_ASYNC);
  33. $mysqli2->query($query,MYSQLI_ASYNC);
  34.  
  35. $connArray = array($mysqli1,$mysqli2);
  36. $processed = 0;
  37. do {
  38. $links = $errors = $reject = array();
  39. foreach ($connArray as $link) {
  40. $links[] = $errors[] = $reject[] = $link;
  41. }
  42. if (!mysqli_poll($links, $errors, $reject, 1)) {
  43. continue;
  44. }
  45. foreach ($links as $link) {
  46. if ($result = $link->reap_async_query()) {
  47.  
  48. if($link === $mysqli1) {
  49. $row1 = $result->fetch_assoc();
  50. } else
  51. if($link === $mysqli2) {
  52. $row2 = $result->fetch_assoc();
  53. }
  54. mysqli_free_result($result);
  55. $processed++;
  56. }
  57. }
  58. } while ($processed < count($connArray));
  59.  
  60. $tEnd = microtime(true);
  61. $tElapsed = $tEnd - $tStart;
  62.  
  63. echo '----------------------------'.PHP_EOL;
  64. echo 'Zapytania asynchroniczne'.PHP_EOL;
  65. echo 'Wynik 1. zapytania: '.$row1['cnt'].PHP_EOL;
  66. echo 'Wynik 2. zapytania: '.$row2['cnt'].PHP_EOL;
  67. echo 'Łączny czas: '.$tElapsed.PHP_EOL;
  68. echo '----------------------------'.PHP_EOL;


Wyniki

[tt]
----------------------------
Zapytania po kolei
Wynik 1. zapytania: 10032000
Wynik 2. zapytania: 10032000
Łączny czas: 7.5110111236572
----------------------------
----------------------------
Zapytania asynchroniczne
Wynik 1. zapytania: 10032000
Wynik 2. zapytania: 10032000
Łączny czas: 3.6900150775909
----------------------------
[/tt]

Tak więc albo gdzieś popełniłem błąd metodologiczny, albo to całkiem dobra metoda. Chętnie sprawdziłbym więcej równoległych zapytań, ale mam u siebie tylko dwa rdzenie tongue.gif
willy
Dzięki za podpowiedzi.

Znalazłem przykład prezentujący dokładnie to o co mi chodzi. Jeśli możecie zerknąć na działanie strony www.findchips.com i podpowiedzieć mi w jak sposób zrealizowane jest wyszukiwanie w tym przypadku będę wdzięczny. Wyszukać można np "lm741"

Pozdrawiam
-willy-
Mchl
Obstawiam, że okresowo ściągają dane od dystrybutorów i całe przeszukiwanie jest na ich własnym serwerze.
willy
Nie wydaje mi się.
Raz, że powielanie baz danych nie ma sensu
Dwa, każda z tych baz jest olbrzymia.
Trzy, dane zmieniają się zbyt szybko.

... a przecież wystarczy, że dystrybutor udostępni adres bazy danych, nazwę użytkownika (tą samą którą dostaje użytkownik korzystający z wyszukiwarki na stronie) oraz hasło i sprecyzuje zapytanie zwracające wymagane dane zgodnie ze strukturą swojej bazy.

Czy takie rozwiązanie nie ma sensu?

-willy-
Mchl
Nie jest to wykluczone. Możliwości jest wiele. Mogli się dogadać z dystrybutorami, że:
udostępnią do wyszukiwania API
udostępnią dane do zalogowania się do bazy danych
udostępnią logi binarne do replikacji

Albo bardziej prozaicznie, mogą wykorzystywać curl do odpytywania wyszukiwarek na stronach dystrybutorów i wyświetlania tych danych u siebie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.