Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][MySQL] Optymalizacja połączenia z bazą
djgarsi
post
Post #1





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

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


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.
Go to the top of the page
+Quote Post
Sephirus
post
Post #2





Grupa: Zarejestrowani
Postów: 1 527
Pomógł: 438
Dołączył: 28.06.2011
Skąd: Warszawa

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


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ć...
Go to the top of the page
+Quote Post
djgarsi
post
Post #3





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

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


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.
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%)
-----


@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.
Go to the top of the page
+Quote Post
Sephirus
post
Post #5





Grupa: Zarejestrowani
Postów: 1 527
Pomógł: 438
Dołączył: 28.06.2011
Skąd: Warszawa

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


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? (IMG:style_emoticons/default/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 :|

Ten post edytował Sephirus 6.02.2013, 17:24:07
Go to the top of the page
+Quote Post
djgarsi
post
Post #6





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

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


@Crozin - niestety nie mam dostępu (chyba) do pliku z logami. To serwer współdzielony.
Go to the top of the page
+Quote Post
Sephirus
post
Post #7





Grupa: Zarejestrowani
Postów: 1 527
Pomógł: 438
Dołączył: 28.06.2011
Skąd: Warszawa

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


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.
Go to the top of the page
+Quote Post
djgarsi
post
Post #8





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

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


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.
Go to the top of the page
+Quote Post
Sephirus
post
Post #9





Grupa: Zarejestrowani
Postów: 1 527
Pomógł: 438
Dołączył: 28.06.2011
Skąd: Warszawa

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


No pasowałoby się przenieść na PDO (IMG:style_emoticons/default/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: (IMG:style_emoticons/default/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 ....


Ten post edytował Sephirus 6.02.2013, 17:47:39
Go to the top of the page
+Quote Post
djgarsi
post
Post #10





Grupa: Zarejestrowani
Postów: 459
Pomógł: 26
Dołączył: 1.06.2009

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


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) (IMG:style_emoticons/default/smile.gif)

Dziękuję za pomoc. Pozdrawiam. (IMG:style_emoticons/default/wink.gif)
Go to the top of the page
+Quote Post
Sephirus
post
Post #11





Grupa: Zarejestrowani
Postów: 1 527
Pomógł: 438
Dołączył: 28.06.2011
Skąd: Warszawa

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


Kombinuj (IMG:style_emoticons/default/smile.gif) Ale.. nie tylko mi się pomógł należy bądźmy uczciwi ;P
Go to the top of the page
+Quote Post
Damonsson
post
Post #12





Grupa: Zarejestrowani
Postów: 2 355
Pomógł: 533
Dołączył: 15.01.2010
Skąd: Bydgoszcz

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


Najpierw sprawdź sobie my_mysql_query. Myślę, że przejście na PDO nic nie da.
Go to the top of the page
+Quote Post
Zigi
post
Post #13





Grupa: Zarejestrowani
Postów: 57
Pomógł: 3
Dołączył: 20.11.2004

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


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.
Go to the top of the page
+Quote Post
sazian
post
Post #14





Grupa: Zarejestrowani
Postów: 1 045
Pomógł: 141
Dołączył: 19.09.2006
Skąd: B-tów

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


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
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: 26.08.2025 - 20:09