Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem z obciążeniem bazy SQL-poddało się wielu
Forum PHP.pl > Forum > PHP
kontrowersje
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
Fafu
wg mnie trochę obciąża funkcja "ereg_replace", polecałbym zamienić na "str_replace".
kontrowersje
Dziękuję za odpowiedź. Niestety to już było testowane i nie pomogło.
Crozin
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.
Spawnm
Proszę dodać BBcode, w przeciwnym wypadku temat zostanie zamknięty .
kontrowersje
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
ChrisB
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?
magnus
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ć.
cojack
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?
krowal
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 ?
netmare
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.
krowal
Cytat
to moim zdaniem fatalny pomysł niezależnie od silnika.

A możesz napisać dlaczego ?
netmare
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).
Methestel
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.
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.