
- Data wpisu: 2009-02-07
- Tagi: Bazy danych, Optymalizacja, PHP, Propel, Symfony, Widok
Szybkie serwisy, zoptymalizowane pod względem zużycia pamięci i ilości odwołań do bazy – czasami mogą być kluczowym elementem w powodzeniu naszego projektu. Chciałbym przedstawić jedną z takich możliwości, czyli użycie w Symfony widoków baz danych. Przykład można zastosować w bazach: PostgreSQL, MySQL, Oracle, itd. Najważniejszym elementem jest to, czy baza danych obsługuje widoki.
Dla przykładu użyję tabeli użytkownik i grupa.
schema.yml
propel:
groups:
id: { type: integer, required: true, primaryKey: true, autoincrement: true }
owner_id: { type: integer, foreignTable: users, foreignReference: id, index: true }
last_user_id: { type: integer, foreignTable: users, foreignReference: id, index: true }
name: { type: varchar, size: 80, index: true }
routing_name: { type: varchar, size: 80, index: true, uniq: true }
description: { type: varchar, size: 400 }
created_at: { type: timestamp }
user_count: { type: integer, index: true }
position_rank: { type: integer }
users:
id: { type: integer, required: true, primaryKey: true, autoincrement: true }
login: { type: varchar, size: 15, index: true, uniq: true }
password: { type: varchar, size: 255 }
name: { type: varchar, size: 255 }
created_at: { type: timestamp }
updated_at: { type: timestamp }
last_login_at: { type: timestamp }
last_request_at: { type: timestamp }
group_id: { type: integer, foreignTable: groups, foreignReference: id, index: true }
Załóżmy, że mamy template w którym pokazujemy 20 grup według ilości użytkowników, w której wyświetlamy: nazwę grupy wraz z linkiem do profilu grupy, właściciela grupy, ostatniego dodanego użytkownika do tej grupy i ilość użytkowników w grupie. Stosując klasyczne wykorzystanie modelów Propela, dostaniemy modele grup z zależnymi 2 modelami użytkowników – właściciel i ostatnio dodany użytkownik. Od razu widać że większość danych jest zbędna, a co z tym idzie wykorzystanie pamięci będzie większe i czas zwracania danych z bazy będzie dłuższy.
Definiowanie widoku (views) w schema
Aby rozdzielić pliki w którym są definicje tabel i widoki, warto utworzyć osobny plik w którym zapiszemy naszą definicje widoku.
config/views_schema.yml
propel:
groups_view:
_attributes: { skipSQL: true, readOnly: true }
id: { type: integer }
name: { type: varchar }
routing_name: { type: varchar }
user_count: { type: integer }
owner_name: { type: varchar }
last_user: { type: varchar }
Kolejnym krokiem jest przygotowanie SQL z definicją naszego vidoku. Dobrym rozwiązaniem jest by każdy widok umieszczać w osobnym pliku i dodawać do sqldb.map, w celu zbudowania widoku z automatu (nie musimy już ręcznie wywoływać SQL).
Tworzymy plik sql
data/sql/views/groups_view.sql
CREATE OR REPLACE VIEW groups_view AS
SELECT groups.id,
groups.name ,
groups.routing_name,
groups.user_count,
owner.login AS owner_name,
last.login AS last_user
FROM groups
JOIN users owner ON owner.id = groups.owner_id
JOIN users last ON last.id = groups.ast_user_id;
Dodajemy widok do sqldb.map
Edytujemy plik sqldb.map i dodajemy nową pozycję
data/sql/sdldb.map
views/groups_view.sql=propel
Kolejnym krokiem jest zbudowanie bazy danych, dla przykładu użyje polecenia, które tworzy modele, dodaje SQL do bazy i wczytuje przykładowe dane.
./symfony propel:build-all-load
Po wygenerowanie powstał model o nazwie GroupsView, teraz tylko nam zostaje dodanie metody, która będzie zwracać 20 grup z największą ilością użytkowników.
Edytujemy GroupsViewPeer.class.php
Dodajemy metodę
public static function getTopGroups( $limit = 20 )
{
$c = new Criteria();
$c->addDescendingOrderByColumn( GroupsViewPeer::USER_COUNT );
$c->setLimit( $limit );
return GroupsViewPeer::doSelect( $c );
}
Metoda ta zwraca 20 obiektów, w których mamy tylko i wyłącznie pola, które będą nam potrzebne do wyświetlenia.
Często na rożnych forach spotyka się opinie, że Symfony jest wolnym i zasobożernym frameworkiem, jeśli nie znamy możliwości, zasad jego działania jak i sposobów optymalizacji to niestety ale taka teoria dla pewnych osób jest prawdziwa. Wykorzystując możliwości baz, takie jak plsql, vidoki, triggery i funkcje można osiągnąć rewelacyjne efekty i obsługa milionowych tabel na “słabym” sprzęcie jest czymś realnym.
Popularne
- Doda i Nergal - Jak to odbiorą fani zespołu Behemoth?
- Koncert Rammstein - Katowice / Spodek
- Symfony - przyśpieszanie Propela z wykorzystaniem widoków (view) baz danych
- Symfony, Propel, PostgreSQL - Multi database (obsługa wielu baz danych w aplikacji)
- Gentoo - Instalacja PostgreSQL 8.3.x i PHP
- pgAdmin v1.10.0 released
- PostgreSQL, pl/python - usuwanie rekordów z zależnymi elementami (plikami)
- Symfony - Propel Lazy Load

Z doświadczenia w wykorzystywaniu widoków na bazie postgresql mogę także potwierdzić że zastosowanie widoków - co za tym idzie ograniczenie ilości wyciąganych danych, zdecydowanie przyśpiesza działanie strony.
Do tego widoki umożliwiają nam tworzenie zaawansowanych zapytań oraz operowaniu na zwracanych danych poprzez prosty model. A wyobraźcie sobie tworzenie, Criteria z JOIN na kilku tabelach, do tego grupowanie etc.
Heh co do opinii że symfony samo w sobie jest wolne także słyszałem, to tutaj zgodzę się z Marcinem że wina leży po stronie nieumiejętnego operowania ORM’em.
Komentarz - autor: Whisller — 2009-02-08 @ 22:57
Rozumiem, że wszyscy iście prawdziwie doświadczeni programiści twierdzą, że Symfony jest demonem szybkości? Zastosowanie widoków, buforowanie, rozsądne wykorzystanie ORMa… naprawdę nie wiedziałem, że bez Symfony nie jest to możliwe…
Komentarz - autor: sobstel - niedoświadczony programista — 2009-02-09 @ 00:39
sobstel - Widzę, że nie zrozumiałeś mojego posta. Nie chodziło mi o żadne porównianie, uważam, że jeśli któś z czegoś korzysta to powinien znać możliwości jak i utrudnienia. To ze ORM’y akurat są jakie są (nie mowie tutaj tylko o PHP) to wiadomo, że wydajnośc trzeba zdobywać trochę “kombinując”
Komentarz - autor: admin — 2009-02-09 @ 00:51
@sobstel: ORM pomaga w tworzeniu i utrzymaniu aplikacji. Jeżeli więc istnieją sposoby na przyspieszenie działania to jak najbardziej należy to robić… Ja widoki stosuje zazwyczaj do raportowania i sprawdzaja się znakomicie.
Komentarz - autor: Kowalikus — 2009-02-19 @ 09:14
Widoki w mysql nie przyspieszaja niczego ani o jote.
Lepiej jest uzywac rozwiazania podobnego do tego:
SELECT * FROM
(
SELECT *
FROM costam c
JOIN coinnego i ON c.id = i.id
) AS tabelka
Komentarz - autor: Maciej — 2009-03-01 @ 11:18
Widok nic Ci nie przyspieszy (mowiac o bazie), ale widokiem dla Propela zawezasz ilosc pol jakie musi wyciagnac + nie ma zaleznych obiektow dla propela, wiec mniejsza pamiec zostanie wykorzystana. Nie chodzilo ze widok sam w sobie jest lepszy, lecz o propela. Co do twojego przykladu to raczej nie ma sensu bo i tak zracasz wszystkie pola. Przeczytaj jeszcze raz moj art i zwroc uwage na to, ze w widoku nie wyciagam wszystkich pol z zlaczonych tabel.
Komentarz - autor: admin — 2009-03-01 @ 12:34
zgadzam sie.
wg mnie widoki po prostu upraszczaja cala sprawe.
w sumie nie ma roznicy miedzy wyzej podanym kodem a odpowiednim kodem poza tym ze:
- widok moze byc cachowany
- wiekszosc RDBS przechowuje widok w zoptymalizowanej formie, w przypadku zapytania jak powyzej server bd musi optymalizowac zapytanie za kazdym razem (co w przypadku niektorych zlozonych zapytan moze byc kosztowne), zwlaszcza jesli to samo zapytanie jest wykonywane tysiace razy na sekunde - zysk jest wtedy znaczny
Komentarz - autor: charlie_edinburgh_napier — 2009-03-03 @ 19:31
A czy np idzie w takim widoku umieścić kilka zapytań do DB ??
Pozdrawiam
Komentarz - autor: jarre1987 — 2009-04-17 @ 13:02
[...] w przykładzie z optymalizacją Propela dobrym nawykiem jest rozdzielenie różnego typu struktur na osobne pliki schema.yml. Główną [...]
Pingback - autor: Symfony, Propel, PostgreSQL - Multi database (obsługa wielu baz danych w aplikacji) | Marcin Chyłek Blog — 2009-05-28 @ 00:48