[PHP] Efektywne przeszukiwanie dużej tablicy |
[PHP] Efektywne przeszukiwanie dużej tablicy |
4.02.2023, 14:25:59
Post
#1
|
|
Grupa: Zarejestrowani Postów: 20 Pomógł: 0 Dołączył: 18.04.2009 Ostrzeżenie: (0%) |
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 |
|
|
4.02.2023, 14:44:34
Post
#2
|
|
Grupa: Zarejestrowani Postów: 6 762 Pomógł: 1822 Dołączył: 11.03.2014 Ostrzeżenie: (0%) |
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?
-------------------- |
|
|
4.02.2023, 16:21:38
Post
#3
|
|
Grupa: Zarejestrowani Postów: 356 Pomógł: 70 Dołączył: 15.07.2014 Ostrzeżenie: (0%) |
Może po prostu przenieś przeszukiwanie na bazę - która ma wbudowane mechanizmy optymalizacyjne - zamiast przeszukiwać to w PHP?
|
|
|
4.02.2023, 21:12:47
Post
#4
|
|
Grupa: Zarejestrowani Postów: 20 Pomógł: 0 Dołączył: 18.04.2009 Ostrzeżenie: (0%) |
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 Rekord to oczywiście jedna z wartości w tej kolumnie VARCHAR ze zwykłymi stringami tekstowymi. |
|
|
5.02.2023, 13:35:22
Post
#5
|
|
Grupa: Zarejestrowani Postów: 6 762 Pomógł: 1822 Dołączył: 11.03.2014 Ostrzeżenie: (0%) |
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. -------------------- |
|
|
5.02.2023, 15:29:35
Post
#6
|
|
Grupa: Zarejestrowani Postów: 20 Pomógł: 0 Dołączył: 18.04.2009 Ostrzeżenie: (0%) |
Czy możesz rozwinąć choćby tą drugą opcję która ma być szybsza ?
|
|
|
5.02.2023, 19:07:44
Post
#7
|
|
Grupa: Zarejestrowani Postów: 6 762 Pomógł: 1822 Dołączył: 11.03.2014 Ostrzeżenie: (0%) |
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. -------------------- |
|
|
5.02.2023, 19:18:15
Post
#8
|
|
Grupa: Zarejestrowani Postów: 6 366 Pomógł: 1115 Dołączył: 30.08.2006 Ostrzeżenie: (0%) |
Do takich celów można też przemyśleć silnik memory.
-------------------- |
|
|
5.02.2023, 22:34:56
Post
#9
|
|
Grupa: Zarejestrowani Postów: 20 Pomógł: 0 Dołączył: 18.04.2009 Ostrzeżenie: (0%) |
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 ? |
|
|
6.02.2023, 07:58:34
Post
#10
|
|
Grupa: Zarejestrowani Postów: 6 762 Pomógł: 1822 Dołączył: 11.03.2014 Ostrzeżenie: (0%) |
Tym zapytaniem uzyskasz wpisy, których brak we `wszystkie`. Założyłeś indeks na `tytul` w `lucek_temp`? -------------------- |
|
|
6.02.2023, 11:13:08
Post
#11
|
|
Grupa: Zarejestrowani Postów: 20 Pomógł: 0 Dołączył: 18.04.2009 Ostrzeżenie: (0%) |
Ok, ten join śmiga Tzn zrobiłeś małą literówkę więc powinien wyglądać tak:
I bez indexów (na polach tytul w obu tabelach) zapytanie trwało 23sek. Natomiast po zrobieniu indexów zapytanie trwa... 0 sec. 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. |
|
|
6.02.2023, 11:51:04
Post
#12
|
|
Grupa: Zarejestrowani Postów: 6 762 Pomógł: 1822 Dołączył: 11.03.2014 Ostrzeżenie: (0%) |
A w jaki celu robisz to porównanie? Chcesz poinformować użytkownika ile jego danych zostanie dopisanych, etc.?
-------------------- |
|
|
Wersja Lo-Fi | Aktualny czas: 15.05.2024 - 03:50 |