Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Prośba o pomoc przy optymalizacji zapytania
grzemach
post
Post #1





Grupa: Zarejestrowani
Postów: 121
Pomógł: 4
Dołączył: 9.06.2007
Skąd: Kielce

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


Witam,
W bazie mam ok 1,3mln rekordów, jest dosyć dużo zapytań, acz nie trwają one długo bo ok 4s każde. Niestety suma sumarum, zapytania te przeciążają bazę mojego hostingodawcy - i często strona jest niedostępna. A że głównie to się dzieje przy odwiedzających botach...

tabele są dwie, ale zapytanie o które mi się rozchodzi nawiązuje tylko do jednej:
  1. CREATE TABLE `PageRankHosts` (
  2. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `link` varchar(150) character SET utf8 collate utf8_unicode_ci DEFAULT NULL,
  4. `pr` tinyint(4) DEFAULT '0',
  5. `created` int(10) UNSIGNED NOT NULL DEFAULT '0',
  6. `fileWithDomains` int(10) UNSIGNED NOT NULL DEFAULT '0',
  7. `statusCreated` varchar(50) character SET utf8 collate utf8_unicode_ci DEFAULT NULL,
  8. `statusNow` varchar(50) character SET utf8 collate utf8_unicode_ci NOT NULL DEFAULT '',
  9. `domainCreated` int(10) UNSIGNED NOT NULL DEFAULT '0',
  10. `lastMod` int(10) UNSIGNED NOT NULL DEFAULT '0',
  11. `optionInfo` varchar(55) character SET utf8 collate utf8_unicode_ci NOT NULL,
  12. `registerIn` text character SET utf8 collate utf8_unicode_ci NOT NULL,
  13. `lastUpdate` int(10) UNSIGNED NOT NULL DEFAULT '0',
  14. `text` tinyint(3) UNSIGNED DEFAULT '0',
  15. `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '3',
  16. `fullWhoIS` text character SET utf8 collate utf8_unicode_ci NOT NULL,
  17. `zwolniona` int(10) UNSIGNED NOT NULL DEFAULT '0',
  18. PRIMARY KEY (`id`),
  19. KEY `link` (`link`),
  20. KEY `created` (`created`),
  21. KEY `pr` (`pr`)
  22. );


Przykładowe zapytanie wygląda tak:
  1. SELECT * FROM PageRankHosts ORDER BY `created` DESC, `pr` DESC LIMIT 926100,30


Jeśli wstawię zamiast * kolumny które mnie interesują (w sumie wszystkie) - nie ma różnicy. Różnica jest gdy usunę "order by", ale przy usunięciu pr, jest to ok 1s, jednak jest to rozwiązanie nie do końca satysfakcjonujące, bo tracę całość sortowania, przenieść sortowanie do PHP? Owszem, ale wyciąganie >200MB danych z bazy do php i tam obrabianie, nie będzie szybsze. Nawet wyciągnięcie samych tych dwóch kolumn nie usprawni tego, bo później trzeba dociągnąć pozostałe dane.

Proszę o wszystkie sugestie.

Ten post edytował grzemach 10.03.2011, 23:36:03


--------------------
Go to the top of the page
+Quote Post
sn1p3r
post
Post #2





Grupa: Zarejestrowani
Postów: 19
Pomógł: 0
Dołączył: 9.03.2011

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


Cytat(grzemach @ 10.03.2011, 23:34:47 ) *
[...]

  1. SELECT * FROM PageRankHosts ORDER BY `created` DESC, `pr` DESC LIMIT 926100,30


wrzuć to, co Ci podaje:

explain select * from PageRankHosts order by `created` DESC, `pr` DESC limit 926100,30

Wstępnie: baza musi zrobić full scan i później zrobić sorty - gdzie indeksy się na nic nie zdają (w tym przypadku)



--------------------
Michał Gruchała
scaleIT.pl
Go to the top of the page
+Quote Post
grzemach
post
Post #3





Grupa: Zarejestrowani
Postów: 121
Pomógł: 4
Dołączył: 9.06.2007
Skąd: Kielce

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


  1. id select_type TABLE type possible_keys KEY key_len ref rows Extra
  2. 1 SIMPLE PageRankHosts ALL NULL NULL NULL NULL 1245506 USING filesort

Cytat
Wstępnie: baza musi zrobić full scan i później zrobić sorty - gdzie indeksy się na nic nie zdają (w tym przypadku)

Wiem, że musi zrobić full skan (sortowanie) i to 2 razy (dwa sortowania). Ale nie mam pomysłu jak przy takiej ilości danych to można by zoptymalizować. Może przerobić bazę, albo wybierać całość danych z bazy i przerabiać w PHP (ale to wydaje się bardzo głupim i złym pomysłem, który nie wierzę że zadziała szybciej).

Może by zmienić tym bazy na innoDB z MyISAM, ale jak widziałem testy wydajności to w tak prostych zapytaniach (bez transakcji) - myisam jest szybsza.

Ten post edytował grzemach 14.03.2011, 12:36:55


--------------------
Go to the top of the page
+Quote Post
Noidea
post
Post #4





Grupa: Zarejestrowani
Postów: 226
Pomógł: 61
Dołączył: 20.08.2010

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


Po założeniu indeksu (jednego!) na dwie kolumny: created i pr oraz pobieraniu samego id EXPLAIN zaczyna wyglądać obiecująco:
  1. EXPLAIN SELECT id FROM PageRankHosts ORDER BY created DESC, pr DESC LIMIT 926100, 30

Kod
id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    SIMPLE    PageRankHosts    index    NULL    created_pr    6    NULL    1    "Using index"

jednak sprawdzam to na pustej bazie, bo nie chce mi się generować miliona wierszy.

W każdym bądź razie załóż ten indeks i sprawdź czy takie zapytanie będzie szybsze:
  1. SELECT prh.*
  2. FROM PageRankHosts prh
  3. JOIN (
  4. SELECT id
  5. FROM PageRankHosts
  6. ORDER BY created DESC, pr DESC
  7. LIMIT 926100, 30
  8. ) prh2 ON ( prh.id = prh2.id )


Ten post edytował Noidea 14.03.2011, 14:10:01


--------------------
Go to the top of the page
+Quote Post
grzemach
post
Post #5





Grupa: Zarejestrowani
Postów: 121
Pomógł: 4
Dołączył: 9.06.2007
Skąd: Kielce

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


o założeniu indeksu na obie te kolumny nie pomyślałem.

Po jego wykonaniu, moje zapytanie nie zmieniło prędkości (4s), ale Twoje wykonuje się ok 2s, więc wynik jest zadowalający. Fakt, chciałbym aby było to <1s, ale przy tej liczbie danych, raczej mało prawdopodobne...

Zwiększyłem ilość danych pobieranych do 100, przez co będzie mniej stron i mniejsze zapotrzebowanie na CPU DB smile.gif

Ten post edytował grzemach 14.03.2011, 15:35:19


--------------------
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 Aktualny czas: 21.08.2025 - 09:07