Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Problem z obciążeniem bazy SQL-poddało się wielu
kontrowersje
post
Post #1





Grupa: Zarejestrowani
Postów: 3
Pomógł: 0
Dołączył: 27.10.2009

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


Witam jestem kompletnym ignorantem w PHP, usiłuję jedynie znaleźć kogoś, kto jest w stanie poprawić poniższy kod, który obciąża bazę SQL. Próbowało wielu PHP-owców, ale nikt nie był w stanie znaleźć przyczyny "mulenia" serwera. Wiem, że jest tu kilka kosmetycznych błędów składni, ale problem tkwi w zapytaniu da bazy, to potwierdzili wszyscy analizujący kod. Strona chodzi pod adresem kontrowersje.net, na cms Drupal, kod który wywala serwer jest następujący:

  1. <?php
  2.  
  3. $right=ereg_replace('{a', '
  4. $right=ereg_replace("{/a}", '', $right);
  5. $right=ereg_replace('{img ', '
  6. $right=ereg_replace('"}', '">', $right);
  7.  
  8. $right=ereg_replace('
  9. ', '
  10. ', $right);
  11.  
  12. $right=ereg_replace("December", "Grudzień", $right);
  13. $right=ereg_replace("November", "Listopad", $right);
  14. $right=ereg_replace("September", "Wrzesień", $right);
  15. $right=ereg_replace("October", "Październik", $right);
  16. $right=ereg_replace("January", "Styczeń", $right);
  17. $right=ereg_replace("February", "Luty", $right);
  18. $right=ereg_replace("March", "Marzec", $right);
  19. $right=ereg_replace("April", "Kwiecień", $right);
  20.  
  21. $right=ereg_replace("May", "Maj", $right);
  22. $right=ereg_replace("Juni", "Czerwiec", $right);
  23. $right=ereg_replace("July", "Lipiec", $right);
  24. $right=ereg_replace("August", "Sierpień", $right);
  25.  
  26. $right=ereg_replace(' ndz.
  27.  
  28. ', ' ndz.
  29.  
  30. ',$right);
  31.  
  32. $right=ereg_replace('
  33. ', '
  34. ',$right);
  35.  
  36. $right=ereg_replace('
  37. ', '
  38. ',$right);
  39.  
  40. $right=ereg_replace('Ostatnio dodane odpowiedzi', '',$right);
  41. $right=ereg_replace('zaktualizowany', '',$right);
  42. $right=ereg_replace('Szybka odpowiedź', '',$right);
  43.  
  44. if (!$user->roles[2]) $right=ereg_replace('Mój blog
  45. # Pisz bloga
  46.  
  47. ', '',$right);
  48.  
  49. print $right;
  50.  
  51. $profile = profile_load_profile($user);
  52.  
  53. $ostatnie_odpowiedzi = $user->profile_ostatnie_odpowiedzi;
  54. if($ostatnie_odpowiedzi < 5) $ostatnie_odpowiedzi = 5;
  55. $ignorowani = '';
  56. $ignorowani .= " AND (UPPER(comments.name) != UPPER('Lustro')) ";
  57. $ignorowani .= " AND (UPPER(comments.name) != UPPER('MaciekS')) ";
  58. $ignorowani .= " AND (UPPER(comments.name) != UPPER('Leyte')) ";
  59. //$ignorowani .= " AND (UPPER(comments.name) != UPPER('zlotousty_klamca')) ";
  60.  
  61. $query = "SELECT node.nid AS nid,
  62. node.uid as uid
  63. FROM {node} node
  64. LEFT JOIN {term_node} term_node_174 ON node.vid = term_node_174.vid AND term_node_174.tid = 174
  65. WHERE (term_node_174.tid = 174) and node.nid >50";
  66.  
  67. $queryResult = db_query($query);
  68.  
  69. while ($nodescount = db_fetch_object($queryResult)) {
  70.  
  71. $comments_priv .= " and comments.nid<>".$nodescount->nid." ";
  72.  
  73. }
  74.  
  75. $query="SELECT comments.cid AS cid,
  76. comments.subject AS comments_subject,
  77. comments.nid AS comments_nid,
  78. comments.pid As comments_pid,
  79. comments.timestamp AS comments_timestamp,
  80. comments.name AS comments_name,
  81. comments.uid AS comments_uid,
  82. comments.homepage AS comments_homepage,
  83. comments.comment AS comments_comment,
  84. comments.format AS comments_format,
  85. history_user.timestamp AS history_user_timestamp,
  86. history_user.nid AS history_user_nid,
  87. node_comments.created AS node_comments_created,
  88. node_comments.changed AS node_comments_changed,
  89. node_comments__node_comment_statistics.last_comment_timestamp AS node_comments__node_comment_statistics_last_comment_timestamp,
  90. node_comments.nid AS node_comments_nid
  91. FROM root_comments comments
  92. LEFT JOIN root_node node_comments ON comments.nid = node_comments.nid
  93. LEFT JOIN root_history history_user ON node_comments.nid = history_user.nid AND history_user.uid = ".$user->uid."
  94. LEFT JOIN root_node_comment_statistics node_comments__node_comment_statistics ON node_comments.nid = node_comments__node_comment_statistics.nid and last_comment_uid<>519
  95. WHERE (node_comments.status <> 0 OR node_comments.uid = ".$user->uid.")".$ignorowani.$comments_priv."
  96. ORDER BY comments_timestamp DESC limit ".$ostatnie_odpowiedzi."";
  97.  
  98. $queryResult = db_query($query);
  99.  
  100. ?>


Będę wdzięczny za wszelkie sugestie i podpowiedzi, jestem również skłonny nawiązać współpracę na zasadzie zleceń z kimś kto da sobie radę z PHP i Drupalem

kontrowersje@kontrowersje.net

Ten post edytował kontrowersje 27.10.2009, 18:34:13
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 13)
Fafu
post
Post #2





Grupa: Zarejestrowani
Postów: 243
Pomógł: 33
Dołączył: 30.01.2008
Skąd: Wrocław

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


wg mnie trochę obciąża funkcja "ereg_replace", polecałbym zamienić na "str_replace".
Go to the top of the page
+Quote Post
kontrowersje
post
Post #3





Grupa: Zarejestrowani
Postów: 3
Pomógł: 0
Dołączył: 27.10.2009

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


Dziękuję za odpowiedź. Niestety to już było testowane i nie pomogło.
Go to the top of the page
+Quote Post
Crozin
post
Post #4





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Skoro wiesz, że to zapytanie do bazy zabija serwer to może pokaż nam to zapytanie w formie jakiej trafia do bazy, a nie wymagaj bezsensownego analizowania koszmarnego kodu, w dodatku nie wstawionego w żadne BBCode.
Go to the top of the page
+Quote Post
Spawnm
post
Post #5





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




Proszę dodać BBcode, w przeciwnym wypadku temat zostanie zamknięty .
Go to the top of the page
+Quote Post
kontrowersje
post
Post #6





Grupa: Zarejestrowani
Postów: 3
Pomógł: 0
Dołączył: 27.10.2009

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


Chętnie dodam to BB coś tam ale nie mam pojęcia co to jest. Jak napisałem jestem ignorantem od PHP i programowania, dlatego szukam pomocy.

Edit: Chyba załapałem o co chodzi z tym BB coś tam, wklejam zatem zapytanie z bazy.

  1. SELECT comments.cid AS cid,
  2. comments.subject AS comments_subject,
  3. comments.nid AS comments_nid,
  4. comments.pid AS comments_pid,
  5. comments.timestamp AS comments_timestamp,
  6. comments.name AS comments_name,
  7. comments.uid AS comments_uid,
  8. comments.homepage AS comments_homepage,
  9. comments.comment AS comments_comment,
  10. comments.format AS comments_format,
  11. history_user.timestamp AS history_user_timestamp,
  12. history_user.nid AS history_user_nid,
  13. node_comments.created AS node_comments_created,
  14. node_comments.changed AS node_comments_changed,
  15. node_comments__node_comment_statistics.last_comment_timestamp AS node_comments__node_comment_statistics_last_comment_timestamp,
  16. node_comments.nid AS node_comments_nid FROM root_comments comments LEFT JOIN root_node node_comments ON comments.nid = node_comments.nid LEFT JOIN root_history history_user ON node_comments.nid = history_user.nid AND history_user.uid = 0 LEFT JOIN root_node_comment_statistics node_comments__node_comment_statistics ON node_comments.nid = node_comments__node_comment_statistics.nid AND last_comment_uid<>519 WHERE (node_comments.STATUS <> 0 OR node_comments.uid = 0) AND (UPPER(comments.name) != UPPER('Lustro')) AND (UPPER(comments.name) != UPPER('MaciekS')) AND (UPPER(comments.name) != UPPER('Leyte')) AND comments.nid<>201 AND comments.nid<>292 AND comments.nid<>344 AND comments.nid<>355 AND comments.nid<>380 AND comments.nid<>450 AND comments.nid<>465 AND comments.nid<>520 AND comments.nid<>522 AND comments.nid<>526 AND comments.nid<>554 AND comments.nid<>579 AND comments.nid<>586 AND comments.nid<>604 AND comments.nid<>624 AND comments.nid<>707 AND comments.nid<>738 AND comments.nid<>739 AND comments.nid<>740 AND comments.nid<>784 AND comments.nid<>800 AND comments.nid<>801 AND comments.nid<>802 AND comments.nid<>803 AND comments.nid<>815 AND comments.nid<>898 AND comments.nid<>934 AND comments.nid<>966 AND comments.nid<>985 AND comments.nid<>1013 AND comments.nid<>1022 AND comments.nid<>1025 AND
  17.  
  18. i tutaj setki pytań o konkretne komentarze z forum
  19.  
  20. comments.nid<>4738 AND comments.nid<>4739
  21. ORDER BY comments_timestamp DESC LIMIT 5


Ten post edytował kontrowersje 27.10.2009, 19:31:35
Go to the top of the page
+Quote Post
ChrisB
post
Post #7





Grupa: Zarejestrowani
Postów: 73
Pomógł: 4
Dołączył: 13.01.2004
Skąd: Bielsko-Biała

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


nie wiem czy to cos da, ale napewno na poczatek bym spróbował wywalić wszystkie comments.nid <> na rzecz jednego not in(x,y,z)

http://dev.mysql.com/doc/refman/5.0/en/com...function_not-in


pozatym last_comment_uid<>519 na stałe ustawione w kodzie? trochę chyba średni ma sens?
Go to the top of the page
+Quote Post
magnus
post
Post #8





Grupa: Zarejestrowani
Postów: 99
Pomógł: 15
Dołączył: 15.11.2007
Skąd: Nowogród Bobrz.

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


1. Zamiast robić takie AND ... AND... AND może lepiej zrobić WHERE nid NOT IN (x,y,z,...)?
2. Sprawdź, czy na tym polu (nid) na pewno jest indeks jak i na wszystkich polach, po których jest robiony JOIN.
3. Ale i tak raczej spowalniać będzie takie coś: AND (UPPER(comments.name) != UPPER('MaciekS')), bo to musi być wyszukiwane tekstowo a nie indeksem. Chyba, że jest na tym indeks pełnotekstowy. Trzeba by to spróbować zamienić na coś, co się da zaindeksować.
Go to the top of the page
+Quote Post
cojack
post
Post #9





Grupa: Zarejestrowani
Postów: 898
Pomógł: 80
Dołączył: 31.05.2008

Ostrzeżenie: (20%)
X----


Rozumiem że indexy pozakładane? Oraz primare keye?

  1. AND comments.nid<>292 AND comments.nid<>344 AND comments.nid<>355 AND comments.nid<>380 AND comments.nid<>450 AND comments.nid<>465 AND comments.nid<>520 AND comments.nid<>522 AND comments.nid<>526 AND comments.nid<>554 AND comments.nid<>579 AND comments.nid<>586 AND comments.nid<>604 AND comments.nid<>624 AND comments.nid<>707 AND comments.nid<>738 AND comments.nid<>739 AND comments.nid<>740 AND comments.nid<>784 AND comments.nid<>800 AND comments.nid<>801 AND comments.nid<>802 AND comments.nid<>803 AND comments.nid<>815 AND comments.nid<>898 AND comments.nid<>934 AND comments.nid<>966 AND comments.nid<>985 AND comments.nid<>1013 AND comments.nid<>1022 AND comments.nid<>1025 AND


a to na cholere?
Go to the top of the page
+Quote Post
krowal
post
Post #10





Grupa: Zarejestrowani
Postów: 561
Pomógł: 72
Dołączył: 15.11.2006

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


Zadaj sobie jedno, ale zaj$#@cie ważne pytanie, czy te JOINY na pewno są Ci niezbędne, czy tych porównań nie da się przerzucić do WHERE ?
Go to the top of the page
+Quote Post
netmare
post
Post #11





Grupa: Zarejestrowani
Postów: 285
Pomógł: 37
Dołączył: 18.12.2007
Skąd: Łódź

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


Ja mam parę pytań:

1. Jaki silnik?
2. Jaka wersja silnika?
3. Ile wierszy zwraca zapytanie bez warunków comments.nid<>...?
4. Setki tych wykluczeń comments.nid to jest 150 czy 1500?
5. Skąd bierzesz wykluczane comments.nid?
6. Muli się tzn jaki konkretnie jest czas wykonania zapytania?

Edit:
Cytat
Zadaj sobie jedno, ale zaj$#@cie ważne pytanie, czy te JOINY na pewno są Ci niezbędne, czy tych porównań nie da się przerzucić do WHERE ?


to moim zdaniem fatalny pomysł niezależnie od silnika.

Ten post edytował netmare 28.10.2009, 21:20:41
Go to the top of the page
+Quote Post
krowal
post
Post #12





Grupa: Zarejestrowani
Postów: 561
Pomógł: 72
Dołączył: 15.11.2006

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


Cytat
to moim zdaniem fatalny pomysł niezależnie od silnika.

A możesz napisać dlaczego ?
Go to the top of the page
+Quote Post
netmare
post
Post #13





Grupa: Zarejestrowani
Postów: 285
Pomógł: 37
Dołączył: 18.12.2007
Skąd: Łódź

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


1. Zmniejszona przejrzystość kodu.
2. Bardziej problematyczna implementacja złączeń left,right i full.
3. Wydajności tym nie poprawisz napewno, a obawiam się że jak zapuścisz na np Postgresie złączenie inner join na dwóch tabelach które mają po 2000000 wierszy i część wspólną 1000000 rekordów, po kolumnie na której z jakiś powodów nie masz indeksów, to przy inner join napewno planer zahaszuje wartości po których ma nastąpić złączenie i szybko upora się z wynikiem, natomiast przy takim explicit joinie po znaku równości myślę że może nie puścić hashowania i wtedy okaże się że położyłeś serwer na kilkanaście minut (nie mam w tej chwili jak sprawdzić, żeby powiedzieć to napewno).
Go to the top of the page
+Quote Post
Methestel
post
Post #14





Grupa: Zarejestrowani
Postów: 46
Pomógł: 10
Dołączył: 30.06.2008

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


Podaj proszę z jakiej bazy danych korzystasz.
Bardzo dużo rzeczy hardkodujesz dlatego domyślam się kod który wkleiłeś jest wersją testową bo jako wersji produkcyjnej nikt chyba by tego nie używał.

Skoro i tak hardkodujesz listę zbanowanych loginów to nie wykonuj na nich niepotrzebnych funkcji. Zamiast
  1. AND (UPPER(comments.name) != UPPER('Lustro')) AND (UPPER(comments.name) != UPPER('MaciekS')) AND (UPPER(comments.name) != UPPER('Leyte'))

zrób:
  1. AND UPPER(comments.name) NOT IN ('LUSTRO', 'MACIEKS', 'LEYTE')

No i nie musisz generować tego php-em bo po co męczyć serwer obliczeniami które zawsze zwracają taki sam wynik. Wrzuć to bezpośrednio do ostatniego zapytania.


Jeśli twoja baza danych obsługuje podzapytania możesz połączyć dwa zapytania w jedno. Np tak:
  1. SELECT comments.cid AS cid,
  2. comments.subject AS comments_subject,
  3. comments.nid AS comments_nid,
  4. comments.pid AS comments_pid,
  5. comments.timestamp AS comments_timestamp,
  6. comments.name AS comments_name,
  7. comments.uid AS comments_uid,
  8. comments.homepage AS comments_homepage,
  9. comments.comment AS comments_comment,
  10. comments.format AS comments_format,
  11. history_user.timestamp AS history_user_timestamp,
  12. history_user.nid AS history_user_nid,
  13. node_comments.created AS node_comments_created,
  14. node_comments.changed AS node_comments_changed,
  15. node_comments__node_comment_statistics.last_comment_timestamp AS node_comments__node_comment_statistics_last_comment_timestamp,
  16. node_comments.nid AS node_comments_nid
  17. FROM root_comments comments
  18. LEFT JOIN root_node node_comments ON comments.nid = node_comments.nid
  19. LEFT JOIN root_history history_user ON node_comments.nid = history_user.nid AND history_user.uid = 0
  20. LEFT JOIN root_node_comment_statistics node_comments__node_comment_statistics ON node_comments.nid = node_comments__node_comment_statistics.nid AND last_comment_uid<>519
  21. WHERE (node_comments.STATUS <> 0 OR node_comments.uid = 0)
  22. AND UPPER(comments.name) NOT IN ('LUSTRO', 'MACIEKS', 'LEYTE')
  23. AND comments.nid NOT IN (SELECT node.nid FROM {node} node LEFT JOIN {term_node} term_node_174 ON node.vid = term_node_174.vid AND term_node_174.tid = 174 WHERE (term_node_174.tid = 174) AND node.nid >50))
  24. ORDER BY comments_timestamp DESC LIMIT 5

Ale i tak największy wzrost wydajności możesz uzyskać przez odpowiednie indeksy.
Jeszcze raz proszę autora o informacje z jakiej bazy danych korzysta. Jeśli autor chce naprawdę konkretnej odpowiedzi proszę o strukturę bazy danych (samą strukturę, bez danych). Wtedy będzie można udzielić bardziej konkretnej odpowiedzi


PS. Co oznacza klamra w "FROM {node} node".? Alias? A może schemat? Nigdy nie spotkałem się z takim zapisem.
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 3.10.2025 - 22:57