Dariusz L.

Dariusz L. programista/
specjalista ds. IT

Temat: mysql+php proste optymalne zapytanie

nie mam możliwości sprawdzenia ani określenia wydajności dwóch sposobów zapytań i przekazywania do PHP, stąd pytanie do Was:
co będzie wydajniejsze?

Mamy takie tabele:

koszulka
-----------
idKoszulka
opis

napisy
-----------
idNapis
opis

koszulka2napis
-----------
idKoszulka
idNapis

w tabeli koszulka jest jeden rekord "koszulka A", a w napisy mamy "napis a", "napis b", "napis c" i wszystkie te napisy sa przypisane do owej koszulki (wykorzystana jest do tego tabela koszulka2napis)

Założenie: koszulek jest 100000, a do każdej są przypisane po 3 napisy

Rozwiązanie 1
----------------------------------
mysql_query("SELECT koszulka.opis AS koszulka, napisy.opis AS napis, koszulka.id
FROM koszulka
INNER JOIN koszulka2napis
ON koszulka2napis.idKoszulka=koszulka.idKoszulka
INNER JOIN napisy
ON napisy.idNapis=koszulka2napis.idNapis")
------
while($r=mysql_fetch_array($q)){
$koszulka[$r['id']]=$r['koszulka'];
$napis[$r['id']][]=$r['napis']
}

Rozwiązanie 2 (skrót myślowy)
----------------------------------
pobierz wszystkie ID koszulek
$tablicaKoszulek[idKoszulka]=koszulka
foreach ($tablicaKoszulek AS $id=>$koszulka){
pobierz napisy dla każdej kolejnej koszulki
$napis[$id]][]=$napis
}

Cel: pobranie i wypisanie danych w stylu:
koszulka1:napis1,napis2,napis3
koszulka2:napis1,napis2,napis3
....


w pierwszym rozwiązaniu do zmiennej $koszulka[id] jest przypisywana koszulka tyle razy ile ma napisów (czyli w tym przypadku trzykrotnie) i to jest minus, plusem jest to, że jest jedno zapytanie do bazy

w drugim przypadku zapytań jest tyle ile koszulek+1, ale każda ze zmiennych przypisywana jest tylko raz.


Co jest bardziej optymalne?

konto usunięte

Temat: mysql+php proste optymalne zapytanie

z doświadczenia - najwydajniej jest napisać funkcję sql

przykład (posgresowy, nie pamiętam pl/sql'a dla mysql, pisane z palca ale idea chyba jasna)


create function pobierzKoszulki() returns setof tablica_koszulek_typ as
$$
declare rec record;
rec1 record;
r tablica_koszulek_typ;
begin
for rec in select id, opis from koszulka into rec loop
for rec1 in select opis from koszulka2napis left join napis on napis_id = id where koszulka_id = rec.id loop
r.napisy := r.napisy ||', '|| rec1.opis;
end loop;
r.nazwa := rec.opis;
return next r;
end loop;
return;
end;
$$
language 'plpgsql';

konto usunięte

Temat: mysql+php proste optymalne zapytanie

Dariusz L.:
Rozwiązanie 1
----------------------------------
mysql_query("SELECT koszulka.opis AS koszulka, napisy.opis AS napis, koszulka.id
FROM koszulka
INNER JOIN koszulka2napis
ON koszulka2napis.idKoszulka=koszulka.idKoszulka
INNER JOIN napisy
ON napisy.idNapis=koszulka2napis.idNapis")
------
while($r=mysql_fetch_array($q)){
$koszulka[$r['id']]=$r['koszulka'];
$napis[$r['id']][]=$r['napis']
}
tak na szybko:

SELECT DISCTINCT koszulka.opis AS koszulka, napisy.opis AS nap....

i powinno byc po jednej koszulce....

Ale zgadzam sie z przedmowca, najlepiej machnac PL/SQLRafał Ziółkowski edytował(a) ten post dnia 04.08.09 o godzinie 13:40

konto usunięte

Temat: mysql+php proste optymalne zapytanie

Rafał Ziółkowski:
SELECT DISCTINCT koszulka.opis AS koszulka, napisy.opis AS nap....

i powinno byc po jednej koszulce....

po jednej koszulce i po jednym napisie, a nie o to chodziło. Nie wiem jak wygląda sprawa z PDO i prepared statements dla mysql, swego czasu nie działało to w ogóle. Jeżeli jednak teraz już działa, to można zrobić rozwiązanie drugie, jednak przez pdo (jednorazowe przygotowanie zapytania z pętli i tylko bind parametrów i execute).
Dariusz L.

Dariusz L. programista/
specjalista ds. IT

Temat: mysql+php proste optymalne zapytanie

Rafał Ziółkowski:
SELECT DISCTINCT koszulka.opis AS koszulka, napisy.opis AS nap....

i powinno byc po jednej koszulce....
to rozwiązanie da to samo co moje ROZWIĄZANIE 1, czyli jedną koszulkę i 3napisy (dopiero 'GROUP BY koszulka.id' da jedna koszulkę i jeden napis)

Musze przyznać, że rozwiązanie z funkcją SQL jest dla mnie po prostu niezrozumiałe i nigdy nie miałem z tym do czynienia, tak więc odpada.

Co do bind i execute, to też nie miałem z tym zbyt wiele wspólnego.

Swoją drogą mój problem wydawał mi się dość pospolity i myślałem, że odpowiedź będzie banalna - teraz wiem jak bardzo się myliłem :)

konto usunięte

Temat: mysql+php proste optymalne zapytanie

Aaaa poczytalem dokladnie co chcesz uzyskac i teraz wiem.
Poszukaj rozwian uzyskania Pivot Table bo tak sie nazywa to co chcesz uzyskac.

PivotTable
http://en.wikibooks.org/wiki/MySQL/Pivot_table

Dynamic crosstabs:
http://www.futhark.ch/mysql/106.htmlRafał Ziółkowski edytował(a) ten post dnia 04.08.09 o godzinie 15:57

konto usunięte

Temat: mysql+php proste optymalne zapytanie

Rafał Ziółkowski:
SELECT DISCTINCT koszulka.opis AS koszulka, napisy.opis AS nap....

a od kiedy to [w znormalizowanej bazie..] uzywamy distinct? przeciez to zabojstwo dla bazy..

konto usunięte

Temat: mysql+php proste optymalne zapytanie

Wojciech Zbigniew Piotrowicz:
Rafał Ziółkowski:
SELECT DISCTINCT koszulka.opis AS koszulka, napisy.opis AS nap....

a od kiedy to [w znormalizowanej bazie..] uzywamy distinct? przeciez to zabojstwo dla bazy..
Hehe, dobra nie bijcie :D

A tak z doswiadczenia, czasem po prostu znormalizowana baza to bialy jednorozec....
Jarosław Lisicki

Jarosław Lisicki programista,
Gadu-Gadu

Temat: mysql+php proste optymalne zapytanie

Może być też:

select k.opis, GROUP_CONCAT(n.opis SEPARATOR ',') as napisy FROM koszulka k, napis n, koszulka2napis kn where k.koszulka_id = kn.koszulka_id and kn.napis_id = n.napis_id group by kn.koszulka_id;

Tylko jako separator trzeba użyć coś co nie występuje w treści napisu.
Marcin K.

Marcin K. Programowanie jest
moim powołaniem,
Alleluja

Temat: mysql+php proste optymalne zapytanie

to pytanie SQL jest mało wydajne przy dużej ilości rekordów, a dokładniej polecenie "INNER JOIN" już lepiej jest wszystko powiązać kluczami w WHERE.

Jeśli zapis się sporadyczny, lecz odczyt bardzo częsty to można się pokusić o kopiowanie wyniku zapytania tabel do tabeli MEMORY w procedurze. Podczas INSERT`a do jednej z tych tabel(koszulka2napis) bedzie wywoływany TRIGGER odpalający procedurę.

Wynik odczytujesz z tabeli memory już śmiesznie prostym SELECT *
FROM tabela memory.

Przy takiej małej ilości danych na rekord nie powinno być problemów z pamięcią. Jednak opisy nie traktuj jako pola typu TEXT tylko VARCHAR są bardziej efektywne, tekstu i tak nie będzie za wiele to tylko koszulki ;)Marcin K. edytował(a) ten post dnia 06.08.09 o godzinie 03:57



Wyślij zaproszenie do