Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Efektywne przeszukiwanie dużej tablicy
Forum PHP.pl > Forum > Przedszkole
loocek
Hej,
Mam problem z przeszukaniem dużej tablicy. Tzn. mam w bazie ok 230k rekordów które pobieram do tablicy i następnie przez formularz na stronie pobieram znowu z 10k rekordów do sprawdzenia i teraz muszę zwyczajnie sprawdzić czy te z formularza występują w bazie. No i robiąc to najprościej w pętli czyli sprawdzając każdy z tych 10k czy jest w bazie 230k długo trwa. Sprawdzenie raptem 2k (a nie 10k) zajmuje już 18sek. No a 10k ? a może i 50k chcąc sprawdzić ? przecież to się będzie wykonywało z 1min...2min - bez sensu.

Czy znacie jakiś sposób na jak największe przyspieszenie tego sprawdzania ? Jakiś algorytm albo funkcje ?
pozdrawiam
trueblue
Jaka to baza? Co masz na myśli pisząc rekord - jedno pole, kilka pól, jakiego typu? Co dokładnie porównujesz? Czy na tabeli są indeksy?
Salvation
Może po prostu przenieś przeszukiwanie na bazę - która ma wbudowane mechanizmy optymalizacyjne - zamiast przeszukiwać to w PHP?
loocek
Jest to MySQL, rekord to mam na myśli jedna z kolumn ze stringami tekstowymi (VARCHAR), tak na tabeli jest indeks.
I muszę sprawdzić czy każdy z tych stringów co ich jest 10k które podaję przez formularz występuje w tej bazie 230k czy nie.


Żle się wyraziłem wink.gif
Rekord to oczywiście jedna z wartości w tej kolumnie VARCHAR ze zwykłymi stringami tekstowymi.
trueblue
Pierwszą metodą jest użycie klauzuli IN. Ale tu ograniczony będziesz zmienną max_allowed_packet (co tu ma związek z długością zapytania).
Drugą metodą, szybszą niż IN w przypadku dużej ilości danych, będzie stworzenie tymczasowej tablicy z indeksem i zapytanie pomiędzy tymi dwiema tablicami.
loocek
Czy możesz rozwinąć choćby tą drugą opcję która ma być szybsza ?
trueblue
1. Tworzysz tymczasową tablicę z polem VARCHAR i indeksem (być może unikalnym) - to możesz zrobić raz, ręcznie.
2. Wstawiasz do niej dane z formularza (INSERT z wieloma wartościami https://www.mysqltutorial.org/mysql-insert-multiple-rows/, ale niekoniecznie wszystkie wartości - patrz: max_allowed_packet).
3. Robisz JOIN
4. Usuwasz dane.
viking
Do takich celów można też przemyśleć silnik memory.
loocek
Na razie ta część MySQL:
Stworzyłem drugą tabelkę lucek_temp do której wrzuciłem 2000 tytułów. I teraz chciałbym uzyskać listę tytułów których nie ma w tej drugiej duzej tabelce. Zatem robię takiego selecta:
select lucek_temp.tytul from lucek_temp join wszystkie ON wszystkie.tytul != lucek_temp.tytul;
i to zapytanie trwa ok 30 sec. po czym proces sam się ubija i wywala mnie z CLI Mysql (bo na raie tam testuję).

Co robię nie tak ?
trueblue
  1. SELECT lt.tytul
  2. FROM lucek_temp AS lt
  3. LEFT JOIN wszystkie AS w ON w.tytul=lt.tytul
  4. WHERE w.tytul IS NULL;

Tym zapytaniem uzyskasz wpisy, których brak we `wszystkie`.

Założyłeś indeks na `tytul` w `lucek_temp`?
loocek
Ok, ten join śmiga smile.gif Tzn zrobiłeś małą literówkę więc powinien wyglądać tak:

  1. SELECT lt.tytul
  2. FROM lucek_temp AS lt
  3. LEFT JOIN wszystkie ON w.tytul=lt.tytul
  4. WHERE w.tytul IS NULL;


I bez indexów (na polach tytul w obu tabelach) zapytanie trwało 23sek. Natomiast po zrobieniu indexów zapytanie trwa... 0 sec. smile.gif
Zatem dorobię sobie jeszcze ten multiinsert rows z formularza PHP do Mysql i wszystko będzie śmigać.

Nie truję już. Dzięki wielkie za pomoc.

trueblue
A w jaki celu robisz to porównanie? Chcesz poinformować użytkownika ile jego danych zostanie dopisanych, etc.?
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-2024 Invision Power Services, Inc.