Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Optymalizacja zapytań
torbicki65
post 28.12.2008, 13:48:29
Post #1





Grupa: Zarejestrowani
Postów: 38
Pomógł: 0
Dołączył: 8.11.2008

Ostrzeżenie: (0%)
-----


Witam
Czy macie jakiś pomysł, na optymalizacje tego zapytania? Generalnie projekt dotyczy naszej klasy (eksportu znajomych - www.znajomi.boo.pl) i ten kawałek skryptu wygląda tak - po pobraniu danych z listy znajomych, wrzuca je w tabele tymczasową i w pętli za każdy kolejny rekord porównuje, czy istnieje już w tabeli docelowej, czy nie (jeśli istnieje, to robi UPDATE, jeśli nie istnieje, to INSERT). Problem w tym, że najczęściej korzystają z tego osoby, które mają dużo znajomych i przy liczbie kilkuset pojawia się problem zasobochłonności.


Kod
$pyt="INSERT INTO tablela_tymczasowa SET id_zn='$id', dane='$imie', miasto='$miasto', profil='$numer'";
   mysql_query($pyt);
      
   // sprawdzanie czy rekordy juz sa - jesli nie, dodaje, jesli tak - aktualizuje
   $pyt=mysql_query("SELECT * FROM $tabela_docelowa WHERE id_zn='$id' AND profil='$numer'");
    
   if(!mysql_fetch_row($pyt))
   {
   $pyt="INSERT INTO $tabelank SET id_zn='$id', dane='$imie', miasto='$miasto', profil='$numer'";
   mysql_query($pyt);
   }
   else
   {
   $staryid=$pyt['id'];
   $pyt="UPDATE $tabelank SET id_zn='$id', dane='$imie', miasto='$miasto', profil='$numer' WHERE id='$staryid'";
   mysql_query($pyt);


i powtarza się ten cykl zapytań dla każdego kontaktu, czyli nawet kilkaset razy (w pętli while).
Domyślam się, że nie jest to optymalne, skoro różne serwery sobie z tym nie radzą (chyba tylko na home.pl było z tym OK).

Generalnie mam jeszcze drugi problem, związany też z MySQL, chodzi o szukanie wspólnych znajomych w dwóch profilach na naszej klasie - tutaj też używam tablicy tymczasowej i wymodziłem takie zapytanie

Kod
$pyt=mysql_query("SELECT * FROM tablica_docelowa WHERE tablica_docelowa.id_zn IN (SELECT tablica_tymczasowa.id_zn FROM tablica_tymczasowa WHERE tablica_tymczasowa.profil='$numer') && tablica_docelowa.profil='$g_numer'");

(przy czym to już idzie normalnie, nie w pętli).
Kilka wyjaśnień odnosnie struktury:
id_zn - jest to numer profilu znajomego na naszej klasie
profil - numer profilu, z którego eksportowane są kontakty

Ten post edytował torbicki65 28.12.2008, 15:20:41
Go to the top of the page
+Quote Post
Zyx
post 28.12.2008, 13:52:57
Post #2





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Odnośnie pierwszego problemu, polecam zapoznać się ze składnią INSERT .... ON DUPLICATE KEY UPDATE automatycznie wykonującą wszystkie te testy na obecność rekordu, który teraz próbujesz robić ręcznie. Dokładniejszy opis znajdziesz tutaj: http://dev.mysql.com/doc/refman/5.0/en/ins...-duplicate.html


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
torbicki65
post 29.12.2008, 01:37:41
Post #3





Grupa: Zarejestrowani
Postów: 38
Pomógł: 0
Dołączył: 8.11.2008

Ostrzeżenie: (0%)
-----


Dzięki, przejrzałem manuala, ale problem jest taki, że pola 'id_zn' i 'profil' nie są (i nie mogą) być unikalne, bo ktoś może być znajomym wielu osób i jednocześnie też mieć wielu znajomych, czyli jedyny warunek, to taki, że wybrana kombinacja obu pól nie może się powtórzyć (np mogą być dane 10|99; 10|50; 12|99; 13|99, ale nie może być 10|99;10|99). Wiem, że nie jest to prawidłowa konstrukcja tabeli, ale generalnie nie chce mi się tego zmieniać teraz, chociaż pewnie będę musiał prędzej czy później.
Myślałem też o REPLACE ale ona też wymaga unikalnego pola.

Odświeżam, może ktoś pomoże, bo ciągle siedzę w tym samym bagnie i nie mam pomysłu.
Rozbiłem tabelę na 2 tabele (bo i tak w końcu kiedyś musiałem, przy aktualnych 80 tys rekordów, ok 10 tysięcy można zaoszczędzić) i teraz wyglądają one w sposób taki:

tabela z danymi
nr profilu (uniq) | dane | miasto

tabela z relacja znajomych
nr profilu | nr profilu znajomego

Więc o ile połowicznie poradziłem sobie z problemem pierwszym i mogę już w jednym zapytaniu MySQL z pomocą "on duplicate key" aktualizować albo dodawać wpis.

Problemem pozostaje jednak druga tabela, gdzie też muszę zaktualizować relacje pomiędzy numerami profili - tutaj nie ma wartości unique, bo może się powtórzyć zarówno pole nr profilu jak i nr profilu znajomego, ale nigdy oba na raz.. więc odpada replace i on duplicate key..

Jakiś pomysł?
Go to the top of the page
+Quote Post
Zyx
post 29.12.2008, 17:04:34
Post #4





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Ale kombinacja id_zn ORAZ profil jest już chyba unikalna, prawda?


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
torbicki65
post 29.12.2008, 18:17:18
Post #5





Grupa: Zarejestrowani
Postów: 38
Pomógł: 0
Dołączył: 8.11.2008

Ostrzeżenie: (0%)
-----


Tak, dlatego mam nadzieję, że nakierujesz mnie, bo naprawdę albo głupieję, albo za dużo o tym myślę... czy da się zrobić dla tej unikalnej kombinacji coś, żeby nie zaprzęgać za dużo php (czyli stara wersja skryptu)..

edit:
OK, nie przypuszczałem, że da się zrobić UNIQUE dla obu pól naraz a nie pojedynczo. Ave!

Ten post edytował torbicki65 30.12.2008, 14:15:06
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 21.06.2025 - 13:43