[sql] kilka pytań

Języki, których efekty są wykonywane po stronie serwera. PHP, ASP czy CGI w połączeniu z bazami danych SQL dają niezwykłe możliwości budowy i zarządzania stron WWW. Tu zadajemy pytania oraz demonstrujemy kod, z którym mamy problem.
krystian_p

[sql] kilka pytań

Post autor: krystian_p »

Jestem początkującym programistą. Mam zamiar stworzyć serwis, w którym będą tyciące materiałów dotyczących miast Polski. Na jedno miasto przypadnie średnio 5-10 artykułów... Taki ogrom informacji może niekorzystnie wpłynąć na pracę serwera.
Mam wiele materiałów dotyczących optymalizacji kodu PHP, jednak nie do końca znam się na stworzeniu kodu, dzięki któremu praca bazy danych będzie sprawniejsza. Przygotowałem zatem kilka przykładów i proszę Was, byście poradzili mi w jaki sposób mam przerobić dany kod, by serwis działał szybciej.


1. Chcę sprawdzić, czy istnieje rekord o 'id' równym liczbie 4:
[sql]$a = mysql_fetch_array(mysql_query("SELECT * FROM tabela WHERE id='4'"));
if($a['id'] == ''){ echo'brak'; } else{ ...[/sql]

2. Chcę wyciągnąć kilka pól z danego rekordu:
[sql]$a = mysql_fetch_array(mysql_query("SELECT pole, pole2 FROM tabela WHERE id='$id'"));
echo $a['pole'];
echo $a['pole2'];[/sql]

3. Chcę wyciągnąć tylko jedno pole z danego rekordu:
[sql]$a = mysql_fetch_array(mysql_query("SELECT pole FROM tabela WHERE id='$id'"));
echo $a['pole'];[/sql]

4. Chcę policzyć, ile jest rekordów, w których 'pole' jest równe liczbie 4:
[sql]$a = mysql_result(mysql_query("SELECT COUNT(*) FROM tabela WHERE pole='4'"),'0');[/sql]

5. Chcę stworzyć listę rekordów, w których 'pole' jest równe liczbie 4:
[sql]$a = mysql_query("SELECT * FROM tabela WHERE pole='4'");
while($r = mysql_fetch_array($a)){
...[/sql]


Tu się zaczyna problem. Czytałem o niejakich indexach. Jak się tworzy indexy w programie PHPMyAdmin dla danego pola? Jakie trzeba wysłać zapytania, żeby utworzyć te indexy? Jakich zapytań trzeba użyć, by skorzystać z indexów?

Ma to jakiś związek z tym, co jest poniżej (jest takie coś w PHPMyAdmin)?
Nazwa klucza Typ Moc Działanie Pole
PRIMARY PRIMARY 1 Edycja Usunięcie id


To jest dla mnie bardzo ważny kod, bo jeśli będzie np. 10.000 rekordów i będę chciał w szybki sposó wyciągnąć tylko 2 w liście to może wystąpić problem...


6. Chcę wyciągnąć id rekordu, w którym jest największy id:
[sql]$a = mysql_fetch_array(mysql_query("SELECT pole FROM tabela ORDER BY id DESC LIMIT 0,1"));[/sql]

7. Chcę edytować wartość danego pola (np. 'pole2') w rekordach, w których 'pole' jest równe liczbie 4:
[sql]mysql_query("UPDATE tabela SET pole2='tekst' WHERE pole='4'");[/sql]

tu chyba też kłamiają się indexy... Ta sama zasada będzie występować podczas usuwania rekordów z wyznaczonymi wartościami?

8. czy warto używać opcji NULL?
strona działa szybciej, jeśli w zapytaniu użyje się kodu:
pole IS NULL

czy, jeśli użyje się:
pole=''

no i przy okazji chciałbym wiedzieć, czy w kodzie PHP szybciej działa kod:
if($a <> '')...
czy
if($a != '')...


9. Dodatkowo chciałbym wiedzieć, czy warto przed includowaniem pliku sprawdzać, czy on w ogóle istnieje, czy lepiej, bo szybciej, użyć od razu takiego kodu:
@include('plik.php')
Nimdil
Posty: 12
Rejestracja: czw sie 02, 2007 12:08 pm

Re: [sql] kilka pytań

Post autor: Nimdil »

Cóż - jeżeli zależy Ci na szybkości to mam kilka uwag:

Po zerowe funkcja mysql_fetch_array jest wolniejsza niż mysql_fetch_row - zalecam tą drugą.

Po pierwsze - zapytanie nr. 1 będzie sprawniejsze, jeżeli utworzysz zapytanie:
[sql]SELECT COUNT(*) FROM tabela WHERE id=4[/sql]
a potem sprawdzisz ile rekordow Ci wyskoczylo. Po pierwsze baza danych nie bedzie musiala przegladac wszystkich krotek a wylacznie kolumne Id. Po drugie zwracasz tylko jedna wartosc zamiast calego wiersza.

Po dalsze - mysql_fetch_row (patrz po zerowe)

Po 5 - nie sprawdzałem dokumentacji MySQL aż tak wnikliwie, ale myślę, że indeksy wynikają z silników (MyISAM itd.) Sprawdź ich opisy w dokumentacji MySQL'a i dobierz stosowny dla Ciebie. Istotna jest tutaj też konstrukcja bazy danych - czy np. zamierzasz używać więzów integralności itp.

Dodam jeszcze, że 10k rekordów to nie jest jakoś tak dużo, żeby należało się bać, czy MySQL to udźwignie. Bazy danych są do dużych ilości danych. Sprawa ma się inaczej, jeżeli stawiasz system na kiepskim serwerze wirtualnym, ale to oddzielna bajka.

Po 6 - ja bym raczej użył funkcji MAX(ID):
[sql]SELECT MAX(id) FROM tabela[/sql]
Nie sprawdzałem jakich funkcji używa mysql, ale do odpowiedzi na powyższe pytanie wystarczy w najgorszym wypadku jedno przejście po tabeli. U Ciebie dochodzi jeszcze kwestia sortowanie.
I nie wiem czemu "SELECT pole..." a nie "SELECT id..."

Po 7 - ja nic problematycznego nie znajduję.

Po 8 - weź pod uwagę, że NULL i pusty string to 2 różne rzeczyi czasami zachowują się odmiennie. Stanowczo warto używać NULL'i bo zyskuje na tym przejrzystość.

<> i != są prawdopodobnie równoważne.

Po 9 - sam sobie odpowiedziales na pytanie. Problem leży w tym, czy na pewno nic się nie skaszani, jeżeli plik się zgubi i nie warto obsłużyć wyjątku. Koszt zapewne jest mały a ew. zysk spory.
[/sql]
Cotter
Nowy
Nowy
Posty: 69
Rejestracja: pn lut 06, 2006 3:11 pm

Re: [sql] kilka pytań

Post autor: Cotter »

Pozwole sobie dodać jeszcze kilka uwag:

Sprawdzanie istnienia rekordu jest najszybsze za pomocą kwerendy:
[sql]
SELECT id FROM tabela WHERE id='4' LIMIT 1
[/sql]
Dlaczego? Ponieważ MySQL zakończy przeszukiwanie sprawdzania tabeli w momencie znalezienia pierwszego rekordu spełniającego warunek WHERE. W przypadku braku LIMIT 1 sprawdzona zostanie cała tabela (o ile nie ma indeksów, UNIQUE na kolumnie lub podobnych). W przypadku COUNT(*) również trzeba sprawdzić całą tabelę.

Jeżeli chodzi o indeksy to MySQL stosuje je sam - nie trzeba pisać specjalnych poleceń. Pamiętaj jednak, że stosowanie indeksów wiąże się ze zwiększeniem rozmiarów (w bajtach) bazy (tabeli). Indeksy warto stosować na kolumnach, o które często powstają zapytania (WHERE). Czasami warto uruchomić serwis bez indeksów i po pewnym czasie przejrzeć statystyki i ustawić indeksy na najbardziej wypytywanych kolumnach.

Tworzenie indeksów w najnowszej wersji phpMyAdmin jest bardzo proste. Pod definicją tabeli (strona z informacją o kolumnach) znajduje się część odpowiadająca za indeksy. Można również kliknąć ikonkę z U koło definicji kolumny.

Teraz jedna najistotniejsza rzecz (choć pewnie o tym wiesz):
Jeżeli należy pobrać kilkanaście - kilkadziesiąt rekordów z bazy to karygodnym jest pobieranie ich pojedynczo (każdy za pomocą oddzielnego zapytania). Tego typu rzeczy są najczęściej spotykanym błędem wśród niedoświadczonych programistów i one powodują wolne działanie baz danych. Należy stawać na głowie, używać JOIN itp aby pobrać dane z bazy za pomocą jednej kwerendy.
ODPOWIEDZ