Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Optymalizacja zapytań
sebekzosw
post
Post #1





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


Mam tabelę, w której znajduje się ponad 2.500.000 rekordów.

jeżeli wykonuje zapytanie sprawdzające źródła odwiedzin:

  1. SELECT `domain`, COUNT(`id`) AS `count` FROM `all_cms_entry` GROUP BY `domain` ORDER BY `count` DESC


to trochę długo się wykonuje:

Pokaż wiersze 0 - 3 ( 4 wszystkich, Wykonanie zapytania trwało 8.5397 sekund(y))

Oto moja struktura bazy danych:
  1. CREATE TABLE IF NOT EXISTS `all_cms_entry` (
  2. `id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `page` varchar(50) COLLATE utf8_polish_ci DEFAULT NULL,
  4. `back` enum('0','1') COLLATE utf8_polish_ci DEFAULT '0',
  5. `domain` varchar(70) COLLATE utf8_polish_ci DEFAULT NULL,
  6. `referer` varchar(100) COLLATE utf8_polish_ci DEFAULT NULL,
  7. `browser` varchar(30) COLLATE utf8_polish_ci DEFAULT NULL,
  8. `platform` varchar(20) COLLATE utf8_polish_ci DEFAULT NULL,
  9. `keyword` varchar(60) COLLATE utf8_polish_ci DEFAULT NULL,
  10. `ip` int(10) UNSIGNED DEFAULT NULL,
  11. `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  12. PRIMARY KEY (`id`),
  13. KEY `page` (`page`,`back`,`domain`,`browser`, `platform`, `keyword`,`ip`),
  14. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=2621940 ;


Da się to jakoś przyśpieszyć?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 16)
nospor
post
Post #2





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Skoro grupujesz po domain to wypadałoby na to pole założyć index
Go to the top of the page
+Quote Post
sebekzosw
post
Post #3





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


hmm, indeks jest nałożony
Go to the top of the page
+Quote Post
cv65
post
Post #4





Grupa: Zarejestrowani
Postów: 94
Pomógł: 9
Dołączył: 12.04.2009

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


Pokaż co Ci mówi EXPLAIN
Go to the top of the page
+Quote Post
sebekzosw
post
Post #5





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


Struktura:

  1. CREATE TABLE IF NOT EXISTS `all_cms_entry` (
  2. `id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `page` varchar(50) COLLATE utf8_polish_ci DEFAULT NULL,
  4. `back` enum('0','1') COLLATE utf8_polish_ci DEFAULT '0',
  5. `domain` varchar(70) COLLATE utf8_polish_ci DEFAULT NULL,
  6. `referer` varchar(100) COLLATE utf8_polish_ci DEFAULT NULL,
  7. `browser` varchar(30) COLLATE utf8_polish_ci DEFAULT NULL,
  8. `platform` varchar(20) COLLATE utf8_polish_ci DEFAULT NULL,
  9. `keyword` varchar(60) COLLATE utf8_polish_ci DEFAULT NULL,
  10. `ip` int(10) UNSIGNED DEFAULT NULL,
  11. `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  12. PRIMARY KEY (`id`),
  13. KEY `page` (`page`,`back`,`domain`,`browser`,`platform`,`keyword`,`ip`)
  14. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=3670017 ;


(IMG:http://imageshack.us/a/img580/4100/explainb.png)
Go to the top of the page
+Quote Post
maly_swd
post
Post #6





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


to:
KEY `page` (`page`,`back`,`domain`,`browser`, `platform`, `keyword`,`ip`),

Nie oznacza ze masz nalozony index na domain!

Takie cos oznacza ze masz poprawnie;)
KEY `domain` (`domain`),


Go to the top of the page
+Quote Post
sebekzosw
post
Post #7





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


  1. SELECT `domain`, COUNT(`id`) AS `count` FROM `all_cms_entry` GROUP BY `domain` ORDER BY `count` DESC


  1. CREATE TABLE IF NOT EXISTS `all_cms_entry` (
  2. `id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `page` varchar(50) COLLATE utf8_polish_ci DEFAULT NULL,
  4. `back` enum('0','1') COLLATE utf8_polish_ci DEFAULT '0',
  5. `domain` varchar(70) COLLATE utf8_polish_ci DEFAULT NULL,
  6. `referer` varchar(100) COLLATE utf8_polish_ci DEFAULT NULL,
  7. `browser` varchar(30) COLLATE utf8_polish_ci DEFAULT NULL,
  8. `platform` varchar(20) COLLATE utf8_polish_ci DEFAULT NULL,
  9. `keyword` varchar(60) COLLATE utf8_polish_ci DEFAULT NULL,
  10. `ip` int(10) UNSIGNED DEFAULT NULL,
  11. `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  12. PRIMARY KEY (`id`),
  13. KEY `domain` (`domain`),
  14. KEY `browser` (`browser`),
  15. KEY `platform` (`platform`),
  16. KEY `keyword` (`keyword`),
  17. KEY `ip` (`ip`)
  18. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=2097153 ;


w skrypcie pokazuje czas ładowania 4sec, jednak w phpmyadmin ładuje, ładuje i ładuje

(IMG:http://imageshack.us/a/img21/8817/localhostlocalhostphpmy.png)

jest dobrze?
Go to the top of the page
+Quote Post
BaN
post
Post #8





Grupa: Zarejestrowani
Postów: 158
Pomógł: 43
Dołączył: 9.11.2007

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


Jest źle, baza nie korzysta z indeksu, zamień COUNT(`id`) na COUNT(*) i zobacz EXPLAIN, powinna skorzystać z indeksu. Jeśli dalej nie, to wykonaj polecenie
  1. CHECK TABLE `all_cms_entry`
I jeszcze raz EXPLAIN. EXPLAIN powinien pokazać korzystanie z indeksu, dodatkowo pewnie dalej będzie tworzenie tabeli tymczasowej i filesort, bo masz sortowanie, ale powinno być szybkie jeśli założy tabelę w pamięci, a nie na dysku. Dużo jest tych unikalnych domen?
Go to the top of the page
+Quote Post
sebekzosw
post
Post #9





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


"Using index; Using temporary; Using filesort" już jest ok w sumie

tych unikalnych domen w sumie to 3 są, jednak powieliłem to wszystko do testów (IMG:style_emoticons/default/smile.gif)

Cytat
zamień COUNT(`id`) na COUNT(*)


zamieniłem i już czuć różnicę (IMG:style_emoticons/default/smile.gif)

Cytat
ale powinno być szybkie jeśli założy tabelę w pamięci, a nie na dysku


da się ustawić, aby zakładało tabele w pamięci a nie na dysku? jeżeli tak to jak?
Go to the top of the page
+Quote Post
maly_swd
post
Post #10





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


"da się ustawić, aby zakładało tabele w pamięci a nie na dysku? jeżeli tak to jak?"

Da sie, ale trzeba miec dostep do ustawien konfiguracyjnych mysql, sa tam odpowiednie zapisy dal tabel tymczasowych i wielkosci przydzielonego ramu.
Go to the top of the page
+Quote Post
mmmmmmm
post
Post #11





Grupa: Zarejestrowani
Postów: 1 421
Pomógł: 310
Dołączył: 18.04.2012

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


ENGINE=MEMORY
http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html
Go to the top of the page
+Quote Post
sebekzosw
post
Post #12





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


a może mi ktoś pomoże jeszcze z jednym problemem. Chce zrobić licznik średniego czasu spędzonego na stronie:

  1. SELECT UNIX_TIMESTAMP(MAX(`date`))- UNIX_TIMESTAMP(MIN(`date`)) AS `sec`, `eid` FROM `all_cms_entry`
  2. WHERE `eid` > 0
  3. GROUP BY `eid`
  4. ORDER BY `all_cms_entry`.`eid` DESC


wynik to:

sec eid
7 2097172
2 2097171
9 2097170
4 2097169
14 2097168

a powinno być suma sekund / ilość rekordów

Średni czas to: 7.2


nie wiem jak to zsumować (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
maly_swd
post
Post #13





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


normalnie powino byc to tak:

  1. SELECT avg(UNIX_TIMESTAMP(MAX(`date`))- UNIX_TIMESTAMP(MIN(`date`)) ) AS `sec`, `eid` FROM `all_cms_entry`
  2. WHERE `eid` > 0
  3. GROUP BY `eid`
  4. ORDER BY `all_cms_entry`.`eid` DESC


pod warunkiem ze masz dobrze zrobiona baze:)

ale u Ciebie moze byc tez tak:

  1. SELECT avg(UNIX_TIMESTAMP(MAX(`date`))- UNIX_TIMESTAMP(MIN(`date`)) ) AS `sec`, `eid` FROM `all_cms_entry`
  2. WHERE `eid` > 0
  3. ORDER BY `all_cms_entry`.`eid` DESC


podaj co to jest to eid... i czemu po tym grupujesz?


Ten post edytował maly_swd 27.09.2012, 18:32:29
Go to the top of the page
+Quote Post
sebekzosw
post
Post #14





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


jeżeli ktoś wejdzie za pierwszym razem na stronę to do bazy leci wpis o wejściu i inne dane. wtedy do sesji zapisuje id pierwszego wejścia (eid). Jeżeli wejdzie drugi raz to również zapisuje dane do bazy + eid. Domyślnie to pole ma ustawiona wartość 0
Go to the top of the page
+Quote Post
maly_swd
post
Post #15





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


i jak? dziala Ci ten przyklad z AVG() co podalem?
Go to the top of the page
+Quote Post
sebekzosw
post
Post #16





Grupa: Zarejestrowani
Postów: 437
Pomógł: 42
Dołączył: 16.04.2007

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


przykład nie działa, błąd #1111 ;/
Go to the top of the page
+Quote Post
maly_swd
post
Post #17





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


  1. SELECT avg(a.sec) FROM (SELECT UNIX_TIMESTAMP(MAX(`date`))- UNIX_TIMESTAMP(MIN(`date`)) AS `sec`, `eid` FROM `all_cms_entry`
  2. WHERE `eid` > 0
  3. GROUP BY `eid`
  4. ORDER BY `all_cms_entry`.`eid` DESC
  5. ) AS a


moim zdaniem cos masz namieszane w danych i zalozeniach, czemu liczycz to w taki sposob? UNIX_TIMESTAMP(MAX(`date`))- UNIX_TIMESTAMP(MIN(`date`)
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: 23.08.2025 - 18:24