Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [mysql] optymalizacja zapytań
wicy
post 2.02.2008, 18:26:11
Post #1





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 2.02.2008

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


Witam,
Jestem słabo obeznany a wziąłem sobie na kark obsługę pewnego projektu.
Projekt prosty - www + kilka skryptów php + baza sql.
Baza jest nie duża: 2 tabele - jedna 10.000 wierszy, druga 900 wierszy.
Problem zaczął się z przekraczaniem limitów zapytań do bazy, choć zupełnie nie wiem z czego się to bierze, gdyż ogół wizyt na stronie dzinnie nie przekracza 20-30. Serwer jednak blokuje bazę wypluwając komunikat:
1226: User 'xxx' has exceeded the 'max_questions' resource (current value: 600000000)
i baza pada na jakiś czas.
Ponieważ limit zapytań ustawiony jest na konkretną bazę uworzyłem kopię bazy z myślą, żeby sprawdzać przed wykonaniem zapytania wartość
'max_questions' i przy przekroczeniu limitu nie narażać się na zwiechę bazy, ale przekierować zapytania do kopii bazy.
Jak sprawdzić
wartość 'max_questions' przed wykonaniem zapytania do bazy??

$link = mysql_connect('xxxl:3306', $username, $password) or die('Nie można się połączyć: ' . mysql_error());
@mysql_select_db($database) or die("Nie udało się wybrać bazy danych");

$result=mysql_query("SELECT * FROM cmentarz WHERE id = ".$m);



Jedyne rozwiązanie jakie na szybko przyszło mi do głowy, dla zmniejszenia ilości zapytań generowanych do bazy sql, to utworzenie kilku kopii tej samej bazy. Kilka skryptów odwołujących się do bazy odwołuje się teraz do róznych baz - każdy do swojej. Teoretycznie powinno to dla 4 baz zmniejszyć ilość zapytań o 75% dla bazy, ale nie mam pojęcia który ze skryptów generuje największą ilość zapytań.
Da się to jakoś sprawdzić? Czy tylko za pomocą admina powidera??

Ten post edytował wicy 2.02.2008, 14:26:04
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 5)
nevt
post 3.02.2008, 11:22:18
Post #2





Grupa: Przyjaciele php.pl
Postów: 1 595
Pomógł: 282
Dołączył: 24.09.2007
Skąd: Reda, Pomorskie.

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


nie tędy droga - sytuacja którą opisujesz jednoznacznie wskazuje na jakiś istotny błąd w którymś ze skryptów php - najprawdopodobniej pętla w nieskończoność odwołująca się do bazy... jeżeli nie jesteś autorem serwisu - może być ci ciężko namierzyć ten bład...
ale możesz spróbować tak: załóż w bazie tulu userów ile jest skryptów korzystających z bazy - każdy skrypt zmodyfikuj tak, żeby łączył się z bazą na innym koncie - przy następnej wysypce serwera dostaniesz komunikat który użytkownik (czyli skrypt) powoduje problem - potem wrzuć tu kod tego skryptu i może jakoś wspólnie znajdziemy przyczynę problemu...


--------------------

-
Oh no, my young coder. You will find that it is you who are mistaken, about a great many things... -
Go to the top of the page
+Quote Post
misiek08
post 3.02.2008, 11:27:52
Post #3





Grupa: Zarejestrowani
Postów: 91
Pomógł: 6
Dołączył: 2.02.2008

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


Można dawać if(!$result = mysql_query[..]){die("Skrypt pobierzdane.php");} w każdym skrypcie zmieniając treść i zobaczyć co wyjdzie.
Go to the top of the page
+Quote Post
wicy
post 3.02.2008, 16:38:03
Post #4





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 2.02.2008

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


Tak też zrobiłem. Dla 5 skryptów korzystających z bazy - 5 baz. Każdy korzysta ze swojej. Wysypuje się najczęściej skrypt:

$username = 'xxxxxxx_1'; - "_1" - wyróżnik bazy dla tego skryptu
$password = 'xxxxxxxxxx';
$database = 'xxxxxxx_1';

$m = $_GET['m'];
$order = $_GET['order'];
$order1 = 'nazwisko';

switch ($order) {
case 'n':
$order1 = 'nazwisko';
break;
case 'l':
} - kilka case-ów do wyboru kolumny sortowanej


//pierwsze 'łączenie' z bazą do pobrania wiersza opisującego nagłówki strony
$link = mysql_connect('sql.xxx.xxx.pl:3306', $username, $password) or die('Nie można się połączyć: ' . mysql_error());
@mysql_select_db($database) or die("Nie udało się wybrać bazy danych");
$result=mysql_query("SELECT * FROM cmentarz WHERE id = ".$m);

$rek = mysql_fetch_array($result);
$id=$rek["id"];
$nazwa=$rek["nazwa"];
$lokal=$rek["lok"];
$kat=$rek["kat"];
$opr=$rek["opr"];

//tu kilka instrukcji php pobierających tekst z pliku zewnętrznego

mysql_close($link);
mysql_free_result ($result);
?>

Wszystko to wstawiło mi się w część <head>. Nie wiem, czy to ma znaczenie?
Dalej leci część <body>. Wyświetlane są pierdółki pobrane z porzedniej operacji SELECT. Potem następuje właściwe pobranie danych z innej tabeli tej samej bazy.

$link = mysql_connect('sql.xxx.xxx.pl:3306', $username, $password) or die('Nie można się połączyć: ' . mysql_error());
@mysql_select_db($database) or die("Nie udało się wybrać bazy danych");
$result=mysql_query("SELECT * FROM polegli p, cmentarz c WHERE miejsce_p='$m' AND c.id=p.miejsce_p ORDER BY ".$order1);

$num=mysql_numrows($result);
if ($num==0)
{
echo $l_nazwisk2;
echo "</td></tr>";
echo "</table><br>";
}
else
{
echo $num
?>
</td></tr>
</table><br>
<center>
<table border="1" cellspacing="2" cellpadding="2" bgcolor="#FFFFFF">

//Tu konstrukcja nagłówków tabeli <th>

<!-- początek pętli wypełniającej tabelę --->
<?
while ($rek = mysql_fetch_array($result))
{
$nazwisko=$rek["nazwisko"];
if ($nazwisko==null) {$nazwisko='-';}
$imie=$rek["imie"];
if ($imie==null) {$imie='-';}
$stopien=$rek["stopien"];
if ($stopien==null) {$stopien='-';}
?>
<tr>
<td><font face="Arial, Helvetica, sans-serif" size=1><? echo $nazwisko; ?></font></td>
<td><font face="Arial, Helvetica, sans-serif" size=1><? echo $imie; ?></font></td>
<td><font face="Arial, Helvetica, sans-serif" size=1><? echo $stopien; ?></font></td>
</tr>
<?
}
echo "</table></center>";
mysql_free_result($result);
mysql_close($link);
}
?>


I to wszystko... Nie wygląda mi na zapętlone zapytanie, ale może się nie znam.
Proszę pomóżcie.
Cała strona do obejrzenia pod http://www.tgcp.polegli.pl
W/w skrypt do obejrzenia pod http://www.polegli.tgcp.pl/miasto.php?lng=...788&order=n
Go to the top of the page
+Quote Post
nevt
post 3.02.2008, 16:47:49
Post #5





Grupa: Przyjaciele php.pl
Postów: 1 595
Pomógł: 282
Dołączył: 24.09.2007
Skąd: Reda, Pomorskie.

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


else
{
echo $num
?>


jaka liczba wyświetla się w tej linijce... przy złej kostrukcji zapytania lub nieprawidłowych danych dla klauzuli WHERE moze wywalać nawet całą tabelę - nie widzę zabezpieczenia w postaci stronicowania wyników, jakiś LIMIT w zapytaniu na przykład...


--------------------

-
Oh no, my young coder. You will find that it is you who are mistaken, about a great many things... -
Go to the top of the page
+Quote Post
wicy
post 4.02.2008, 23:19:51
Post #6





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 2.02.2008

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


$num=mysql_numrows($result);
if ($num==0)
{
echo $l_nazwisk2;
echo "</td></tr>";
echo "</table><br>";
}
else
{
echo $num

Liczba nazwisk w bazie. Jeśli $num==0 wyświetla "Brak" (zmienna tekstowa wprowadzona dla różnych wersji językowych). Jeśli $num<>0 wyświetla liczbę wierszy.
Czy ustalenie limitów, stronicowania ma wpływ na error #1226?? Czy to tylko raczej "ładny styl" pisania?
Jeśli nie ma to wpływu na ilość zapytań do bazy, to póki co odpuszczę kosmetykę.

Aha.. trochę mało przejrzyście podałem przykład. Oczywiście dalesze odczyty wierszy i konstrukcja tabeli są w części po ELSE
I oczywiście chyba zrobiłem błąd bo zamknięcie bazy jest tylko w części ELSE. Więc dla miast zerową liczbą osób $link się nie zamyka.
Czy to może być przyczynąquestionmark.gif?

No i nie pomogło sad.gif
O ile z błędu zniknęło "max_question" o tyle pojawił się komunikat:
#1226 - User 'xxx' has exceeded the 'busy_time' resource (current value: 600000000)

O co tu jeszcze może chodzić? Czy zapytanie wykonuje się za długo?

Ten post edytował wicy 3.02.2008, 17:06:14
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: 26.06.2025 - 07:12