Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MYSQL][PHP]Wolne zapytanie do bazy, jak przyśpieszyć ?
Forum PHP.pl > Forum > Przedszkole
jarekhunter
Witam wszystkich, mam tabelkę w bazie strony.
w niej kolejno takie kolumny:
  1. ID int(11) NOT NULL AUTO_INCREMENT,
  2. kat int(11) NOT NULL,
  3. pod int(11) NOT NULL,
  4. typ_id int(11) NOT NULL,
  5. typ int(1) NOT NULL,
  6. autor varchar(40) NOT NULL,
  7. opis text NOT NULL,
  8. zawartosc text NOT NULL,
  9. DATA datetime NOT NULL,
  10. cena int(11) NOT NULL,
  11. wyswietlen int(11) NOT NULL,
  12. PRIMARY KEY(ID)


Pobieram 3 ostatnie lub 3 pierwsze strony z tym że warunkiem jest kolumna typ
Pobieram dane np. tak

  1. SELECT ID FROM strony WHERE typ=0 ORDER BY ID DESC LIMIT 3;

lub
  1. SELECT ID FROM strony WHERE typ=0 ORDER BY ID ASC LIMIT 3;

lub
  1. SELECT ID FROM strony WHERE typ=1 ORDER BY ID DESC LIMIT 0,3;

lub
  1. SELECT ID FROM strony WHERE typ=1 ORDER BY ID ASC LIMIT 0,3;


w tych ostatnich robię stronicowanie wiec limit ma 3 wyświetlić rekordy ale zaczynające się od jakiegoś tam już wcześniej.

A teraz z czym mam problem, przy 100 wpisach wczytuje się to błyskawicznie, ale przy 1000000
Czyli przy milionie takich wpisów wykonuję się to u mnie 25,98 sekund.

Dlaczego taki długi czas skoro pobieram tylko 3 wiersze questionmark.gif
Może powinienem jakoś oznaczyć kolumnę typ dla lepszego indexowania tylko jak to zrobić questionmark.gif
Nawet jeśli próbuję stronicować samo pole ID to muli się to strasznie.
Jak radzą skrypty na których są forum internetowe, tam jest tego miliony i działa szybko, dlaczego u mnie się tak to muli questionmark.gif

Gdzie popełniam błąd questionmark.gif
Czy całkowicie wyrzucić dane tekstowe na inną tabele questionmark.gif
Jak sobie panowie radzicie z takimi problemami.

Dziękuję serdecznie za pomoc.
bełdzio
daj index na typ

id jest kluczem głównym więc nie ma potrzeby dawania mu indexu
rytek
A nie na ID?
Uczyli mnie, że zwykle robi się na pole, które jest PRIMARY KEY;

Jak nie, to na typ:
  1. CREATE INDEX Index_typ ON strony (typ);
bełdzio
jak jest primary key to już nie trzeba indexu

//ad dół polecam się na przyszłość :-)
rytek
No, czyli albo źle zrozumiałem, albo mój nauczyciel prawi głupoty.
Poszukałem trochę i faktycznie, PRIMARY KEY jest automatycznie indeksem...
Dzięki Bełdzio za naprostowanie.
jarekhunter
Panowie, tak ID jest indeksem głównym i dlatego ustawiam na niego PRIMARY KEY,

kolumna typ może zawierać (0,1,2) tak do 9, w przyszłości może będzie więcej jeszcze nie wiem.

Boli mnie fakt że przy milionie wpisów by wyświetlić 3 ostatnie wpisy zajmuję to do 30 sekund, po tym oczywiście sql zrobi cache i jest szybciej, ale gdy chce kolejną podstronę otworzyć to dalej mam taki długi okres oczekiwania..

Wracając do tematu co proponujecie questionmark.gif

Próbowałem sortować ją według
ALTER TABLE strony ORDER BY ID oraz BY ID, typ.

Oba przypadki w niczym mi nie pomagają.
Dlaczego sql się tak muli questionmark.gif, przecież nie pobieram dużo danych ani nie losuję ich, pobieram 3 rekordy a on ma taki cholerny problem z ich wczytaniem.

Jak działają zatem cms'y For Dyskusyjnych, jest bardzo dużo danych w tabelach, dużo wierszy i mimo to wczytuje się to w dobrym czasie.
Można by zrobić cachowanie po stronie php. ale sami zobaczcie mam np. pobieranie 3 ostatnich i 3 pierwszych stron, z tym nie ma problemu.
a jak chce wyświetlać taki milion stron i np. po 10 je odczytywać na stronę, dla każdej nie zrobię cachowania bo to mija się z celem użycia baz danych sql.

Napiszcie mi co robię w takim razie źle..

Mój sprzęt to.
2x3GHz, 2,5 GB ramu, serwer postawiony jest na unixie. na moim localhoscie
Dysk 320 GB SATA, bardzo ładne transwery, na sprzęcie nie pracuje nic więcej co by mogło zamulać pracę serwera.
Testy dokonuję na localhoscie z konsoli mysql.

Serwer jest zainstalowany "Xampp" (Najbardziej był skonfigurowany pod SEO itp.), przekonfigurowanego delikatnie.
Dla poprawy cachowania zmieniłem ustawienia z /etc/my.cnf
Kod
skip-locking
key_buffer = 64M
max_allowed_packet = 1M
table_cache = 512
query_cache_size=246M
sort_buffer_size = 4M
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K                    
thread_stack = 64K


Poprawiło to jedynie cachowanie, ale 1 raz wczytać zawartość muszę i się muli, później już jest na tej zawartości ok
Ale gdy użyję po SELECT SQL_NO_CACHE
to czas jest od 25 do 30 sekund, moim zdaniem katastrofa jak na takie dane.
Na końcu oczywiście włączyłem cachowanie żeby nie było że mam bez.

Przed testami miałem standardową konfigurację i było to samo.
sad.gif
bełdzio
w polach tekstowych trzymasz dużo danych? dodałeś index na typ?
jarekhunter
Z tymi danymi różnie, dla testu nie mam ich wiele, ale później będzie ich znacznie więcej,

Przy tworzeniu tabeli ustawiłem klucz PRIMARY KEY dla ID.
Kolumny typ nie oznaczałem, jaki index mam ustawić dla typ by mogły się powtarzać ale również by po nich szybko sortował questionmark.gif

Obecna tabela ma taką postać:
  1. CREATE TABLE `strony` (
  2. `ID` int(11) NOT NULL AUTO_INCREMENT,
  3. `kat` int(11) NOT NULL,
  4. `pod` int(11) NOT NULL,
  5. `typ_id` int(11) NOT NULL,
  6. `typ` int(1) NOT NULL,
  7. `autor` varchar(40) COLLATE utf8_polish_ci NOT NULL,
  8. `opis` text COLLATE utf8_polish_ci NOT NULL,
  9. `zawartosc` text COLLATE utf8_polish_ci NOT NULL,
  10. `data` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  11. `cena` int(11) NOT NULL,
  12. `wyswietlen` int(11) NOT NULL,
  13. PRIMARY KEY (`ID`)
  14. ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;


Na innych miejscach strony również biorę pod uwagę pola kat,pod,ID
Czyli w warunku daje np. kat=1 AND pod=6 AND typ=1
Przykładowo.
bełdzio
wrzuć
  1. ALTER TABLE strony ADD INDEX ( typ );
jarekhunter
Dzięki czyli nie index a key muszę przypisać dodatkowym polom czyli.
  1. CREATE TABLE `szablony` (
  2. `ID` int(11) NOT NULL AUTO_INCREMENT,
  3. `kat` int(11) NOT NULL,
  4. `pod` int(11) NOT NULL,
  5. `typ_id` int(11) NOT NULL,
  6. `typ` int(1) NOT NULL,
  7. `autor` varchar(40) COLLATE utf8_polish_ci NOT NULL,
  8. `opis` text COLLATE utf8_polish_ci NOT NULL,
  9. `zawartosc` text COLLATE utf8_polish_ci NOT NULL,
  10. `data` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  11. `cena` int(11) NOT NULL,
  12. `wyswietlen` int(11) NOT NULL,
  13. PRIMARY KEY (`ID`),
  14. KEY `typ` (`typ`)
  15. ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci


Dodatkowo w warunku where uwzględniam kat, pod czy je też mogę dodać na tej samej zasadzie co typ questionmark.gif
bełdzio
możesz, aczkolwiek miej na uwadze, że im więcej masz indeksów tym dodawanie rekordów jest wolniejsze
jarekhunter
Dzięki bełdzio bardzo mi pomogłeś, napisz mi jeszcze czy można z konsoli mysql wyłaczyć cachowanie, tzn by strona która mi się ładuje była bezpośrednio wczytywana z bazy a nie z cache, bo w zapytaniu jak dodam SQL_NO_CACHE - to są na nowo pobierane dane, ale nie chce wszystkich zapytań zmieniać dlatego chciał bym na chwile wyłączyć cachowanie dla testów a później włączyć..

Pomożesz questionmark.gif
bełdzio
spróbuj

  1. SET session query_cache_type=0;
jarekhunter
Czy jak sortuję np. w ten sposób.

  1. SELECT * FROM strony WHERE typ=0 ORDER BY `wyswietlen` DESC,`nazwa` ASC LIMIT 5;


Czy jest sens wtedy nadawać dla nazwa i wyswietlen index questionmark.gif
wystarczy np. taki przykładowo
  1. ALTER TABLE szablony ADD INDEX (`nazwa`,`wyswietlen`);


Czy to spowolni mi bazę questionmark.gif
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.