Tudy ne: zlo jménem JPA

Jak už jsem dříve psal, jsem odkojený Oraclem a vždycky mi udělá radost, když to funguje. Oracle umí být rychlý jako “divá svině” (tu hlášku jsem si půjčil od kamaráda Tibora, díky TeeBee). Když už Oracle nejede, málokdy je to jeho chyba.Jak se svět (a CPU) zrychluje, tak nějak se začíná zanedbávat “příprava”. Všechno je agilní, začíná se dělat bez toho, aby bylo jasné CO to má vlastně dělat a JAK to má funovat. Místo zdržování ne-cool fází systémové analýzy promarňujeme čas opakovanou reimplementací téhož jednou tak a pak onak a furt to nějak není ono. Když to začne být ono, zjistíme, že jsme úplně uhnuli od původního záměru a třeba i od business procesu. Nová doba. Co už. V Greenhopperu máme pěkně zelený burndown – projekťák je spokojený, šéf je spokojený. Nakonec – někdy to i funguje a někdy dokonce i seje. Za půl roku zjistíme, že není dokumentace a ta co máme, není aktuání. Život je změna.

Jak se nám zrychluje ta doba a je tlak na time-to-market, přecházíme na free-cool-in technologie. Jednou z nich je JPA. Měl jsem to štěstí dělat na mnoha zajímavých projektech a JPA bylo na několika posledních. Na mockách a testech to jede dobře. OTLP via ORM jede dobře, entita letí sem, entita letí tam, tohle změnit, tohle zakomitovat a pak… Pak se to pokazí. Jednou za měsíc potřebujete spustit report a ejhle. JPA vám přes ORM nacpe celou databázi do paměti aplikáče. Co bych dostal jednoduchým SQL dotazem z Oracle za 10 sekund zabere giga RAMky a trvá 5-10 minut. Úplně stejně je na tom engine jednoho mnou používaného toolu. Potřebuju vidět v jeho konzoli běhy konkrétní úlohy spuštěné v intervalu třeba 15 minut 2 dny zpátky a ono se to celé nahrne do RAM a tam se v tom přehrabuje java. Posledně z toho byl Out of memory. Na produkci taková událost vždycky vyvolá nadšení. Má to 2GB RAM jen pro JVM, má to najít pár záznamů a naplnit jeden přehled a jeden strom detailů. Skončilo to zvýšením xmx na 8GB pro sychr. Na pády na produkci opravdu nikdo není zvědavý. Bohužel původní virtuální stroj se už nedal nafouknout, hardware byl na stropě. Museli jsme migrovat na jiný server a suma sumárum nás ta sranda stála 4 lidi 14 dní práce a rozrýpali jsem 3 prostředí. Zase – obyčejným SQL je to task na 10 sekund a Oracle si ani nevšimne, že něco dělá.

Troufám si tvrdit, že tvůrci těch aplikací nejsou žádní hlupáci. Jsou to kluci samý certifikát, samý SCJP/OCJP a třeba i nějaký na JPA. Jen si prostě usnadnili život a používají to, co znají. Bohužel nezkusili to po sobě taky použít. A když jo, tak ne po naplnění daty. A když jo, tak těch dat nebylo dost. A když jo, neměli reprezentativní vzorek. Nakonec, v nejhorším si v datacentru pořídíme silnější železo. Vyjde to levněji, než to měsíc ladit a refaktorovat. Odpustek na technologický dluh. Ekonomika se musí hejbat! Bullshit.

Je to asi 3 roky, co jsem šel na pohovor do firmy, která se chlubila, že za den zpracuje (celosvětově) 30M finančních operací. Pak jsme si chvíli povídali o tom, že to dělají v JPA, jak se řeší performance tuning a deadlocky – no a když jsem jim řekl, že bez JPA by nic z toho skoro nepotkali, nebyli zrovna nadšení byli ne-úplně nadšení. Paní z HR mi pak stroze napsala, že bych v té firmě nebyl šťastný 🙂 – abych se porozhlédl jinde. Pár měsíců nato jsem nastoupil do jiné firmy – a je tam zase JPA a zase se ladí – performance.

Radši ani nepsat o tom, jak vypadá SQL dotaz vygenerovaný Hibernatem, že se i JPA programuje QL jazykem, tentokrát JPQL/HQL. Že JPA má chyby, Hibernate HQL má chyby, Oracle má chyby, aplikáč má chyby… a ty se potkávají – když to nejmíň potřebujete. Potkají se vám až na produkci a budete je řešit pod tlakem. S borďákem, nebo dvěma za zády a s vidinou pěkného článku na facebooku, nebo Twitteru. Reputační riziko, když už pomineme to operační. Že datový model vygenerovaný JPAčkem je všechno jiné než semanticky čistý s aplikovanými normálními formami, aplikačně agnostický relační datový model, do kterého se podívá databázista (třeba z oddělení DWH/BI) a ví která bije. Model vygenerovaný pro JPA vypadá jako hromada pytlíků na bordel ne-úplně pořádek. Jeden by se rozbrečel. Primární klíč v každé tabuli má název ID, aby se to dobře poznalo 🙂 A když už má i normální formy, jsou v něm entity svázány dědičností. V relační databázi katastrofa vyžadující nadbytečné joinování – a to není zadarmo – na prostředky = na peníze.

Až budu jako freelancer dělat svou aplikaci, za kterou se nebudu chtět po 2 letech stydět, určitě nebude na JPA. 🙂 Použiju framework, do kterého dám svoje SQL jako resource a nechám na něm tu špinavou práci konverzí na entity. Ještě ho musím najít. 🙂 A možná bude stačit jen obyčejný preparedStatement A.K.A. JPA native query. Kdo zažil, kolik práce se dá v Oracle DB SQL udělat s hinty, klauzulí WITH, analytickými funkcemi, nebo třeba příkazem MERGE, bude se mnou souhlasit. Data má dělat databáze. K tomu je a to umí rychle. Java pak může dělat svou business logiku.

Posledně se mi rozbil na Oracle prováděcí plán po odstávce jedné DB. Vytáhl jsem ze šablony SQL, dal ho do SQL Developeru, podíval se na prováděcí plán, zapnul hintem goal ALL_ROWS, na WITH klauzuli (subquery factoring) aplikoval hint MATERIALIZE a z 5 a 1/2 hodiny rozbitého běhu bylo 3,5 vteřiny. Práce na 10 minut, změna v jediném souboru.

Choose the Right Tool for the Task!

FURT VE STŘEHU!