Použijte DB konečně naplno - zapomeňte na DB layer
U spousty PHP projektů se člověk setká s databázovým layerem. Na tom není v zásadě nic špatného, objektový layer nad sadou funkcí je nutná věc. Špatné je, že většina těchto layerů "podporuje" více různých DB (ano, to je špatné), a to pochopitelně na úrovni nejnižšího společného jmenovatele. Takže se přes layer umíte připojit k DB, provést SELECT či INSERT, získat další záznam, případně chybové hlášení, a ... to je vlastně všechno.
Neuvěřitelná primitivnost. Jenže dnešní databáze toho umí mnohem více.
Problém je, že pokud se dostanete za hranice primitivního ANSI-92 SQL, 16 let stará věc, tak podobnost databází končí. Pokud definujete uloženou proceduru či funkci v T-SQL, nebude fungovat na Oracle s PL-SQL a už vůbec ne v primitivním MySQL.
Dokonce i trivialita jako je vynucení použití určitých indexů, nebo i návrh VIEW nebude všude fungovat stejně. Definice pro cizí klíče je odlišná. Ani datové typy nejsou stejné. LIMIT x není stejný. Nad Oraclem namísto IDENTITY či AUTOINCREMENT polí budete muset dělat sekvence a triggery pro BEFORE INSERT na daných tabulkách.
Databázové layery, které pracují s více typy databází, mají smysl pro některé open-source projekty. Tam je rychlost nadřazena nad výkon a spolehlivost. Jejich programátoři se poté omezují na nejprimitivnější SQL, "aby to fungovalo všude". Osobně ovšem ze všech projektů, kde jde o výkon, databázový layer pro model více databází odstraňuji (pokud tam je), ponechávám jen DB jedinou a optimalizované objekty pro ni, a snažím se vyždímat z této konkrétní použité databáze maximum.
Pro jeden velký portálový projekt (stovky tisíc pageviews denně) používám SQL Server 2008 a IIS7 právě proto, že T-SQL je mocný nástroj, a to i při propojení na PHP jako back-end. Na výkonu "skriptovaného" PHP zde tak v podstatě nezáleží, použije se jen pro prezentační část, a na to je PHP velice dobré.
Databázový layer pro více DB není znakem pokroku, u projektů postavených pro jeden konkrétní systém je často naopak znakem toho, že daný vývojář zná jen základy SQL a nic víc. Vše ostatní "prasí" na aplikační úrovni, přestože zpracování na serveru bývá rychlejší a výhodnější.
Asi založím "Ligu proti databázovým layerům" s podtitulem "Použijte vaši DB konečně naplno a nativně (a nejenom na primitivní SELECT a INSERT)" :-)
Dnešní rychlokvašná "MySQL generace" totiž vůbec neví, že databáze jsou určené k tomu, aby se v nich programovalo.
Pod to se ti klidně podepíšu nebo se rozdělím o náklady na provoz domény :) Nicméně model je stále dobrá věc, jen je potřeba na něj potřeba nahlížet trošku jinak, než jako na implementaci ActiveRecordu, ORM či něčeho podobného.
Já nějak nevím ale vždycky mi stačilo používat právě jen ten SELECT, INSERT atd. K čemu cokoliv jiného? Právě proto, že si udělám maximum na straně DB pak nepotřebuji vyrábět a posílat nějaké šílené dotazy z front/backendu.
Na straně DB si vytvořím například proceduru na ověření uživatele a tu pak jen zavolám s příslušnými parametry. Pak už je IMO jedno čím jí volám (třeba u PHP je volání MSSQL procedur blbě vymyšlené). Layer se pak stará jen o správné a bezpečné předání dotazu, vše ostatní už je na úrovni databáze.
IMO layery nenesou vinu na tom, že mnoho lidí nepoužívá pokročilé možnosti databází. U MySQL je chyba v databázi, protože tam ty možnosti prostě nejsou ale u jiných databází je to spíš o tom, že manuály čte málokdo a nějakých školení nebo alespoň článků na téma pokročilé práce s databázemi je jako šafránu.
Třeba bys mohl tady na blogu nějaký takový seriál rozjet. Těm z nás, co už nějaké základy a informace mají to rozšíří obzory, ti ostatní se dozví, že databáze skrývají víc než se na první pohled zdá. Sám bych něco takového napsal ale na to myslím nemám dost znalostí.
1. Vies nam uvies nejaky prakticky priklad, na ktorom si robil, ktory vyuziva nove veci v T-SQL ?
2. Ty pises formulare rucne? A ked chcem pridat pole, tak zakazdym pridavas <input name="telefonne_cislo"> do view, a do model pridavas INSERT INTO (..., telefonne_cislo) VALUES (..., $_POST["telefonne_cislo"])
No tak neviem mne pride @zakaznik.update_attributes params[:zakaznik] o dost jednoduchsie (ruby)..
A napriklad PHP Symfony generuje formulare automaticky, teda cely kod je <?php echo $form ?> Ty to vazne pises rucne?
[3] nechápu proč do článku o DB pleteš formuláře. Máš problém s chápáním psaného textu?
Upozornění pro méně chápavé: v článku se nepíše o používání přímo DB funkcí či nepoužívání DB layeru vůbec, ale o tom, že tento layer nemá být používán jako "nejnižší společná množina" pro veškeré možné databáze (typická vlastnost DB layerů) a fukčnost tomuto primitivnímu pojetí uzpůsobena (pokud člověk nevyžaduje podporu více DB, což v 99% není nutné).
Prosim ta nebud ofenzivny. Ja sa ta to pytam, pretoze ma zaujima akym sposobom programujes, a mojim cielom nie je ta urazit alebo ponizit. Chcem iba diskutovat, a zistit ako to robis.
Běžný programátor si sice vystačí s primitivním neobjektovým driverem jako je SQL Server 2008, ale profík potřebuje pořádný nástroj, kvalitní objektovou vrstvu.
[6] to je opět nepochopeno ;) Nad sqlsrv() se samozřejmě postaví objektová vrstva, ale dedikovaná pro tento konkrétní server.
Opakuji to podruhé: píšu zde o layerech, které implementují pár základních a stejných funkcí pro veškeré (velice rozdílné) DB, s tím že většina autorů se poté omezuje jen na jejich používání, namísto aby 100% programovala pro danou DB. Výsledkem je naprosto neefektivní kód, není to LINQ, ale jen obal na pár funkcí. Sám programátor se musí starat o optimalizace pro danou konkrétní DB. To, že volám $db->fetch() a ne sqlsrv_fetch_array() mě opravdu nevytrhne. Ani Zend DB Adapter není řešení.
V tomto smyslu je DB layer doslova škodlivá věc (a v desítkách open-source projektů co jsem viděl v podstatě jen takto používaná - k databázi se přistupuje tak "aby to fungovalo všude", tedy neoptimálně).
Ukaž mi DB layer pro PHP, co dokonale a 100% převádí T-SQL na PL-SQL a na uložené procedury v MySQL, to samé pro relace, typy v tabulkách (včetně autoincrement), indexy, nakonec i obyčejné (složitější) SELECTy a VIEWs a začnu jej používat ;)
Neber to prosím zle, vážím si moc tvé práce na Nette, ale třeba Dibi je pouze obal na pár jiných funkcí, který nic z tohoto neřeší. Pokud člověk má 100% používat danou DB, takový layer mu vůbec nepomůže při migraci na jinou DB (ani při 100% využití té jedné zvolené). Vše je najednou zcela jinak.
Databázový layer přeci není od toho, aby pomohl při migraci na jinou DB. Tobě vadí Database Abstraction Layer (mně také http://latrine.dgx.cz/zlo-si-rika-database-abstraction-layer...), ale to je něco jako odmítat trabanta slovy, že automobily jsou nesmysl.
Třeba zrovna u dibi jsem zdůrazňoval, že v žádném případě neřeší:
- zajištění kompatibility SQL příkazů
- emulace funkcí chybějících některým databázím
přesto je to stále databázový layer.
Dále - ačkoliv se všechny databáze značným způsobem liší (což je vynikající, nejen pro konkurenční prostředí), mají určité části téměř identické - například výsledky dotazu jsou tabulkou, tedy sérií polí skalárních hodnot. Zapouzdření a zpracování result setu pak může řešit společný kód. Pokud nechci do každého layeru pro každou databázi kopírovat stejné třídy, mohu efektivněji spojit více layerů a sdílet společné knihovny. Výsledkem je pak databázový layer podporující více databázových serverů.
Výsledkem je stále efektvní nástroj. Při migraci těžko pomůže, ale k tomu nikdy určen nebyl.
[8] nejedná se (jen) o migraci. Jedná se o to, že pokud chci výkonnou aplikaci, MUSÍM ji napsat pro konkrétní DB na míru. V tomto mi Dibi rozhodně nepomůže. Otázkou tedy je, proč tam mít layer pro 10 databází, když ten kód stejně nebude fungovat na ničem jiném než té zvolené.
Na toto stačí malý tenký objekt, který zapoudří klasické funkce PHP a přidá k nim to, co potřebuji pro danou DB.
Když se podíváš na jakoukoliv open-source aplikaci kolem, tak na optimalizaci pro jednotlivé DB se zcela rezignuje a "prasí" se to, právě díky DB layerům pro více DB, jen v nejzákladnějších SQL příkazech. I obyčejné phpBB fórum by mohlo být několikrát výkonnější kdyby rezignovalo na podporu hromady databází.
Naivní lidé si pak myslí, že "více je lépe", ale ono to v případě DB rozhodně neplatí :)
[9] Zcela souhlasím, aplikace také píšu na míru konkrétní databázi a na zapouzdření mi stačít tenká mini-vrstva (mini + DB = dibi) a Dibi je mi tedy obrovským pomocníkem.
Stále ale nerozumím, proč když budu distribuovat takových sedm tenkých vrstev pro různé DB v jednom archívu, tak je to najednou škodlivá věc.
Už vůbec nerozumím příkladu s phpBB fórem. Předpokládám, že toto fórum bylo od počátku také psáno na míru konkrétním databázím (množné číslo) a k zapouzdření také použili tenké vrstvy. Proč by to mělo být v tomto případě prasení?
[10] předpokládáš špatně. Stáhni si phpBB. V SQL příkazech uvidíš jen CREATE TABLE, žádné VIEWs, uložené procedury či funkce, žádné triggery, ba ani žádná referenční integrita a CASCADE při DELETE. Typická open-source aplikace používá DB layeru jako jediné možné funkčnosti. Optimalizace pro jednotlivé DB nulová.
A to je průser, na tom se shodneme snadno :)
Dej lidem DB layer (nutně umějící tak 10% funkcí dané DB, aby to fungovalo i v jiných), a oni přestanou přemýšlet, co je mimo něj...
[11] "žádné VIEWs, uložené procedury či funkce, žádné trigger" - to je přece optimalizace, konkrétně pro nejrozšířenější databázový stroj MySQL 4.1. Fórum phpBB se nestalo populární proto, že by fungovalo jen s nejnovější verzí Oracle, ale proto, že funguje na nejširším spektru hostingů.
Hlásíme se z druhého břehu - mimo svět PHP a MySQL:)
Zcela vážně - tentokrát s Radkem musím souhlasit, což nebývá vždy. Pokud chcete slušně psát interakce s databází, na DB layerech pro webové aplikace se to nikdy nenaučíte.
Naprosto souhlasím s tím, že vše, co manipuluje s daty patří do databáze, zvláště kritické operace. A protože jsou databáze rostě rodílné, nelze napsat jakýkoliv rozumný universální DB layer, jak to nazýváte. Enormní to je pak na vyspělejších databázích s vnitřním programovacím jádrem a jejich rozšířeníma - typicky Oracle, MSSQL a z OS PSQL, Firebird.
A to mluvíme jen o možnostech interního kodu typu T-SQL nebo P-SQL. A kde máte rozšíření přímo pro DB stroj (Oracle - Java, MSSQL - SP přímo v .NET) ? A kde máte využití databázových farem ? A jak zpracováváte cross link query mezi databázemi ? To jako vše natáhnete na aplikační vrstvu a pak výsledky odešlete zpět ?
Pokud již cítíte nutnost layeru nebo wrapperu, tak zásadou je vždy 1 typ DB stroje, maximální využití možností dané DB (kaskádová referenční integrita, optimalizované indexy pro daný stroj, uložené procedury pro řízení update, výchozí hodnoty polí, transakce, updatable views, triggers) a pokud možno využít middleware (aplikační server), tam, kde se to vyplatí.
Jedinou omluvou budiž layer pro konkrétní aplikaci, která ŘÍZENĚ předpokládá běžné přepínámí mezi několika typy databází za chodu aplikace - ale to jsou výjimky.
Nicméně nenapadám ani Davida Grundla, protože vlastní DB layer pro projekty které si píše sám nepatří tak ani do katagorie obecných DB layerů, ale do pokusu o middleware.
Radek H. spíše napadá bezhlavé používání předžvýkaných knihoven, o nichž ti, co je používají, nic nevědí a jsou na hony vzdáleni skutečnému programování v databázích. Bohužel má pravdu v tom, že to je běžný jev právě u webových aplikací.
Já znám a umím pracovat s jedinou databází - MSSQL, s Radkem proto souhlasím;)Ale Radku vyprdni se už na to PHP a začni psát články o ASP.NET, LINQ ,WPF ... což jsou jediné pokrokové a funknční technologie.
Proti tomu, že společné headery oklešťují možnosti při prgání na minimum, nemám ani čárku, s tím nelze než souhlasit. Jen ale v rychlosti bleskněte nad tím, proč u opensource projektů layery pro tolik druhů DB jsou. Jde právě o to, že je to opensource aplikace, která už je autorem hotová (resp. základ), a už jako jakýsi produkt nabízena masám - širokému spektru uživatelů, kteří nedisponují stejným základem jako je typ DB. Proto se to píše "primitivně", aby to fungovalo všude.
Naproti tomu je něco jiného masivní aplikace stavěná na míru zákazníkovi (či sobě, etc.), kde jsou dopředu jasně daná specifika, technologie, a je možné už při jeho vývoji počítat právě se známými dispozicemi, a vytěžit z nabízené funkcionality maximum. Souhlas tedy i s tím "proč se omezovat", ale nesrovnával bych to s opensrc.
Hlásím se ze světa Javy. Tam máme bubíčka (ORM)jménem Hibernate, který má odstiňovat programátora od různých dialektů databází. Na několika aplikačních projektech se ukázalo, jak kontraproduktivní tento přístup je a to nemluvě o projektech na DWH a to i tehdy, kdy od začátku je jasné že nikde jinde než na Oraclu to nepoběží. Takže musím s Radkem jen souhlasit. Mnohem lepší je přístup knihovny iBatis, jejíž klon je i pro .NET.
Dle mého názoru je migrace na jinou databázi čistě obchodně marketingový trik, jak obalamutit manažery, kteří drží budget.
[16] Podpora více DB rozšiřuje potenciální klientelu. Nikdy nevíte, kdy za Vámi přijde klient, který má zájem o Váš produkt ale místo MySQL má na serveru například PostgreSQL nebo MSSQL.
Buď vyhovíte (máte podporu pro více DB nebo připravíte verzi pro tu jeho) nebo se omluvíte - což pro Vás může (a samozřejmě nemusí) mít nepříjemné následky. Z vlastní zkušenosti vím, jací dokáží být především čeští klienti zmr*i, když není po jejich :)
Ale to s layery asi příliš nesouvisí.
[16] hibernate rozhodně nemá (alespoň ne prvoplánově) odstiňovat programátora od různých dialektů sql, ale poskytovat objektově relační mapping. V tom je rozdíl. (Tím nijak neobhajuju hibernate, jsou projekty, kdy se může hodit, stejně jako existuje spousta scénářů, kdy je díky své těžkopádnosti nepoužitelný)
Použijte DB konečně naplno - zapomeňte na relační DB a přejděte na ODBMS
;)
Nedávno jsem zaslechl i v celku rozumný argument proč se pro komunikaci s DB v aplikaci omezit jen na základní a nejjednodušší SQL příkazy a vše ostatní provádět v aplikačním kódu:
Databáze, není-li distribuovaná (což ovšem přináší řadu potíží), nemůže svůj výkon zvyšovat do nekonečna. HW možnosti jsou stále ještě omezené, než aby jeden server dokázal obsloužit miliony požadavků současně. Proto, ty opravdu veliké aplikace mají vlastní, co nejnabušenější, DB server, kde je jen konzolový OS a databázový systém. Aplikace samotná je pak nahrána na více dalších serverech v síti (webové farmě) a na databázi má jen co nejjednodušší SQL dotazy, aby ji zatěžovala co nejméně. Data tedy jen přečte a zpracuje si je už sama (seřadí, propojí, seskupí atd.). Když nedostačuje výkon, přidá se jen další aplikační server do farmy, což s databázovým bohužel udělat nejde. V tomto přístupu je pak jakýkoli aplikační kód v databázi celkem kontraproduktivní.
Nicméně DB layery nejsou vždy vhodné ani pro tento přístup, protože se ne zcela snadno kontroluje, jaké SQL dotazy do databáze nakonec pošlou. Nicméně nemuset v kódu slepovat vlastní SQL je velmi vítané...
Co se týče databáze tak preferuji FireBird. V jeho PSQL se uložené procedury a triggery píší daleko lépe a srozumitelněji než třeba v MSSQL. Existuje k němu skvělý nástroj pro správu – IBExpert, který svou přehledností a snadností ovládání v lecčems předčí i SQL admina (určitě do té doby, dokud MS bude používat ten příšerný standardní grid). Embeded verze pak umožňuje provoz databáze bez jakékoli instalace čehokoli, stačí jen k exe souboru přihodit jedno DLL a všechny funkce fungují (byť tedy o něco málo pomaleji) úplně stejně jako při na samotném DBS (včetně UDF), stačí jen změnit connection string. A samozřejmě jedním z podstatných faktorů je i cena 0,- Kč, což oproti třičtvrtě mega pro jeden CPU za MSSQL nebo několika milionům za Oracle obvykle zákazníci preferují. Pravda, bankovní systém bych si nad FireBirdem asi dělat netroufl, ale na menší aplikace, kde DB bude řekněme pod 50 GB, to stačí. Podle testů je totiž FireBird výrazně nejvýkonnější opensource DBS.
Pod .NETem jde používat také bez problémů a Entity framework s ní plně počítá, takže už podporuje i LINQ.
[20] naprosto hloupý argument. Takže tabulku co má pár GB budeš celou tahat na klienta, zatěžujíce SQL server, ethernetové rozhraní i klienta, a tam ji dále zpracovávat abys získal 1KB výsledných dat pro zobrazení? A takto bude GB dat pro každý dotaz tahat stovka (či tisíc) klientů zaráz? Ne, toto opravdu není řešení. Zkus trošku přemýšlet a nešířit bludy.
[22] myslím, že pisatel měl na mysli spíše "jednoduché dotazy" ano, ale nějaké další zpracování dat na straně DB již ne.
používám k práci MSSQL staršího data vydání a je fakt, že tam musím dost často nahrazovat chybějící funkce právě nějakou uloženou procedurou, a nebo se smířit s tím, že do aplikace poputuje 100 záznamů a ja zpracuji jen 10 - protože často to jinak ani nejde. 2008 je na tom lépe - z toho, co jsem četl - nikdy sem ji ale nezkoušel.
každopádně jsem toho názoru, že objektové databáze řeší všechny problémy ;D relační databáze jsou prostě pruda :)
[22] Tak nějaká WHERE podmínka je přeci samozřejmost, která se vyplatí v drtivé většine případů, ale když to chci seřadit třeba podle nějakého vypočteného pole, pak už je to na uváženou...
Přátelé, kamarádi,
Jak tady pročítám článek a diskuzi, tak vidím, že někdo má více a někdo méně zkušeností s obsluhováním přístupu k DB a designu aplikace jako takové. Nechci a nebudu jmenovat.
Každopádně bych zde rád prezentoval svůj názor k danému tématu - každý sebelepší nástroj jde použít naprosto nevhodným způsobem a míra správnosti použítí se projeví časem dříve nebo později.
Spolupracoval jsem na řekněme větsím množství softwarových projektů v .NET (žádný malý weby, ale velký systémy pro zákazníky jako je Škoda auto, státní zpráva, Fisher ... a teď právě CommerzBank) a v podstatě na každém projektu se k databázi přistupovalo jinak. Prošel jsem si proto stádii DataSetů, DataObjects.NET, vlastních DB vrstev s ručně psanou CRUD+ ve stored procedures/view až jsem narazil na nHibernate. A teď přijde celé jádro mého postu - správně použitý nHibernate je naprosté jádro úspěchu. Někdo předemnou se zmiňoval o Hibernatu (java matce nHibernatu) a nijak jej nechválil, ale já to musím udělat - chválím tento nástroj.
Vše, o čem se zmiňuje článek - stored procedures, views, triggers atd. - lze využít, efektivně použít a dokonce validovat, testovat a celé funkční schéma databáze (včetně SPs, views, triggers) mít generované práve nHibernatem. Takže drahé a kritické operace nad databází optimálně rozvrhnu mezi business logiku, DAO a samotnou databázi. A přitom psát aplikaci pohodlně bez duplicit v kódu a nesmyslnýho neustálýho CRUD definic kdekoliv. Názor, že veškerá logika by měla být v databázi je prastarý názor a naprosto neefektivní. A naopak, vše v aplikační logice je taky špatný. Proto tu máme three-tier architekturu, která právě umožňuje variabilitu a hlavně použitelnost toho nejlepšího z daných vrstev.
Děkuji.
[25] mnou navržené systémy běží v řadě bank, třeba v Komerční bance na dealingu (systém ИVAN a ИVAN Dealing; dnes jsou ve verzi 5, do verze 4 to bylo plně koncepčně a částečně programátorsky moje dílo) jimi protékají stovky miliard obratu (Total Solutions, s.r.o.), v PPF burzovní a mnoha dalších. Také je tam pochopitelně použita 3úrovňová architektura, jako DB výhradně Oracle a PL-SQL.
Ale zde se bavíme o návrhu poměrně jednoduchých webových aplikací a portálů, kam se aplikační server (většinou) zcela nehodí.
[26] Své zkušenosti jsem uvedl pouze jako přidanou vánu příspěvku. Každopádně koncepční rozdělení do three-tier neznamená, že nutně musí bežet na třech mašinách. Jde především o uspořádání logických celků z pohledu funkčnosti v aplikaci. Je třeba se držet nějakých standardů i v tool oblasti.
Samozřejmě jde napsat aplikace bez znalostí těchto principů a bastlit business logiku do code-behind a tím tak naproste znepříjemnit život všem okolo. Proto to držení se principů, které znají ostatní a vedou k lepšímu výsledku.
A nejen to - každý, kdo je schopen napsat web, tak se mu tato činost líbí. Pokud ne, tak toho nechá, jde dělat něco jiného a své dílko ani nedokončí. Pokud ano, tak má ambice stát se profesionálem a měl by se těmito principy zabývat v rámci zlepšování se. Proto by se o tom mělo diskutovat i v rovině webových aplikací.