Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL] Optymalizacja połączenia z bazą
Forum PHP.pl > Forum > PHP
djgarsi
Witam.

Od jakiegoś czasu mam problem z przeciążeniem serwera, spowodowanym nieoptymalnym połączeniem z bazą (tak twierdzi hostingodawca).
Struktura tabeli z największą ilością danych (200tys rekordów) to:
  1. CREATE TABLE IF NOT EXISTS `pliki` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `nazwa` text NOT NULL,
  4. `www` int(2) NOT NULL,
  5. `identyfikator` int(11) NOT NULL,
  6. `data_dodania` datetime NOT NULL,
  7. `wyswietlen` int(11) NOT NULL DEFAULT '0',
  8. `pobran` int(11) NOT NULL DEFAULT '0',
  9. `ocena` int(11) NOT NULL DEFAULT '0',
  10. `polecane` tinyint(1) NOT NULL DEFAULT '0',
  11. `blokada` tinyint(1) NOT NULL DEFAULT '0',
  12. PRIMARY KEY (`id`),
  13. KEY `www` (`www`,`identyfikator`),
  14. FULLTEXT KEY `nazwa` (`nazwa`)
  15. ) ENGINE=MyISAM DEFAULT CHARSET=latin2 AUTO_INCREMENT=211448 ;

Przykładowe zapytanie do bazy, które powoduje obciążenie to:
  1. $zap = 'SELECT www,identyfikator FROM pliki WHERE www="'.$www.'" and identyfikator="'.$identyfikator.'"';
  2. $query = mysql_query($zap) or die('Blad zapytania');


Czy ktoś mógłby mnie naprowadzić jak można to zoptymalizować?
Proszę o pomoc.
Sephirus
Cytat
ENGINE=MyISAM


Jak duży ruch masz na tej tabeli? IMHO wystarczy ją dać na InnoDb - z tym że z fulltexta musiałbyś zrezygnować...
djgarsi
Cytat(Sephirus @ 6.02.2013, 17:01:24 ) *
Jak duży ruch masz na tej tabeli?

Niby niewielki ten ruch, bo 40-50tys odsłon dziennie to nie dużo, a jak widać nieoptymalny system stworzyłem.
Crozin
@Sephirus: W tym konkretnym przypadku MyISAM może być nawet szybszy od InnoDB przy odczycie danych. Dodatkowo, jak sam zauważyłeś InnoDB w wersji MySQL 5.5 nie obsługuje indeksu pełnotekstowego (dopiero wersja 5.6 to wprowadza).

@djgarsi:
1. Jesteś pewien, że to ta tabela i to zapytanie jest wąskim gardłem? W tym przypadku mamy do czynienia z "idealną sytuacją", bo na dobrą sprawę wszystkie dane mogą być odczytane bezpośrednio z indeksu, z pominięciem tabeli samej w sobie.
2. Pamiętaj, że ilość rekordów wcale nie ma aż tak dużego znaczenia w tabeli. Najlepiej jakbyś pokazał nam slow query loga.
Sephirus
MyISAM jest kiepski jak jest dużo odczytów/selectów bo blokuje całą tabelę - nie wiem ale podejrzewam że to może być to akurat.

EDIT: @Crozin - musisz mi dać więcej info czemu w tym przypadku MyISAM miałby być szybszy? tongue.gif

Ogólnie jak w MyISAMIE na autoincremencie są dziury i jest dużo odczytów to MyISAM nie wyrabia, z tego co sam praktykuje to raczej nigdy nie używam go dla tabel, które muszą mieć szybki odczyt wiec stąd nie kumam do końca :|
djgarsi
@Crozin - niestety nie mam dostępu (chyba) do pliku z logami. To serwer współdzielony.
Sephirus
hmm bez tego będzie ciężko, musiałbyś obserwować procesy w MySQL (o ile też masz do tego dostęp - SHOW PROCESSLIST) i jak masz fart to zobaczysz jakieś długo wykonujące się zapytanie lub dużo zapytań naraz.

Może masz niewydajną aplikacje - z dużą liczbą zapytań. Z czego korzystasz do MySQL? mysql_*** czy PDO? Może udałoby Ci się policzyć ile na żądanie masz zapytań itp.

Bo tak jak zauważył Crozin to wcale nie musi być to konkretne zapytanie.
djgarsi
Cytat(Sephirus @ 6.02.2013, 17:32:56 ) *
hmm bez tego będzie ciężko, musiałbyś obserwować procesy w MySQL (o ile też masz do tego dostęp - SHOW PROCESSLIST) i jak masz fart to zobaczysz jakieś długo wykonujące się zapytanie lub dużo zapytań naraz.

Może masz niewydajną aplikacje - z dużą liczbą zapytań. Z czego korzystasz do MySQL? mysql_*** czy PDO? Może udałoby Ci się policzyć ile na żądanie masz zapytań itp.

Bo tak jak zauważył Crozin to wcale nie musi być to konkretne zapytanie.

Obecnie uzywam mysql_***, jednak po tej akcji na bank przepiszę serwis na PDO.
Sephirus
No pasowałoby się przenieść na PDO smile.gif Aczkolwiek to problemu nie rozwiąże.

W bazie masz dostęp jedynie do swojej bazy - możesz masz też dostęp do bazy "mysql" tam masz tabelę "slow_log", która ma info o tych "slow queries".

Proponuje Ci na szybko, wziąć całą apkę, zrobić backup kodu, napisać w jakimś wszędzie dołączanym pliku funkcję:

  1. function my_mysql_query($query) {
  2. $t = microtime(true);
  3. $result = mysql_query($query);
  4. error_log('tu info o zapytaniu i trwaniu: '.(microtime(true) - $t));
  5. return $result;
  6. }


Albo coś w tym stylu i nadpisałbym we wszystkich skryptach mysql_query => my_mysql_query. Jak dobrze przygotujesz tą funkcję, dostaniesz info jakie zapytanie ile Ci zabiera czasu i ile jest zapytań na request.

EDIT: smile.gif Przede wszystkim wrzuć to zapytanie samo do bazy i zobacz w ile się wykona (nadaj jakieś tam te pola które wrzucasz z PHP) - możesz też dodać zaraz po SELECT klauzulę SQL_NO_CACHE aby mieć pewność ,że czas jest poprawny

  1. SELECT SQL_NO_CACHE ....
djgarsi
Niestety nie mam takich danych "slow_log". A jak widać przydałyby się bardzo.
No cóż, na początej przepiszę system na PDO, a później będę kombinował z tą funkcją my_mysql_query (bardzo ciekawy pomysł, prosty a zarazem trudny do wpadnięcia na niego) smile.gif

Dziękuję za pomoc. Pozdrawiam. wink.gif
Sephirus
Kombinuj smile.gif Ale.. nie tylko mi się pomógł należy bądźmy uczciwi ;P
Damonsson
Najpierw sprawdź sobie my_mysql_query. Myślę, że przejście na PDO nic nie da.
Zigi
Nie wiem dokładnie jak zachowują się indeksy w MySQLu, ale może zrób indeks w kolejności KEY `www` (`identyfikator`, `www`) jeśli poprawiłoby to selektywność wybierania rekordów.
Ile rekordów zazwykle zwraca to zapytaniu ? Po zapytaniu wydaje mi się że jeden, ale wolę się upewnić, bo może jest za duzy ruch sieciowy niepotrzebnie generowany.
sazian
z tego co słyszałem to mysqli jest szybsze od pod
a na pewno będzie łatwiej przerobić z mysql_*

po przejściu na obiektowe mysqli można bardzo łatwo wykonać test "my_mysql_query", wystarczy zrobić klasę dziedziczącą po mysqli i przeciążyć query
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.