neděle 3. července 2016

Javisté a databáze - základní chyby

Na školení jsem všem implicitně vynadal, že nikdo pořádně neumí používat ani JDBC, ale chtějí (dobře) používat JPA nebo JTA. A co teprve, aby rozuměli trochu tomu, co jejich zacházení způsobí na databázovém serveru ...
Pak se diví, že jim to celé padá na hubu - typicky začnou optimalizovat SQL, ale marně. Jen málokoho napadne, že databázi dávají kapky - pro každý váš požadavek databáze alokuje nějaké zdroje v operační paměti, přidělí vlákno, příkaz zabere nějaké místo na file systému, a databáze čeká až na signál od vás, že už jste hotoví.
Tož si překontrolujte, jestli si databázi nepřetěžujete ...
  • zavíráním statementů
    • kolikrát za sebou generujete stejný prepared statement?
    • nezavíráním statementů
    • jak dlouho má db držet statement?
    • kolik stejných prepared statementů držíte najednou?
    • poslední pomoc: omezit počet použití konexe z poolu, pak jí AS nuceně zavře a otevře novou (Payara)
  • nezavíráním result setů
    • jak dlouho má db držet nalezená data, kurzor?
    • kolik dat to je?
    • fetch size
  • zbytečně dlouhými transakcemi se spoustou změn
    • víte, co se děje v databázi?
    • víte, že i zdroje databáze jsou omezené?
  • nemazáním dočasných tabulek, vytvořených v poolovaných konexích
    • je to v podstatě leak, zapomenutá data pak můžou být náhodně nalezena jiným dotazem, čili hypoteticky to může být i bezpečnostní díra.
  • nadměrným využíváním indexů nebo naopak jejich absencí
    • každé vložení dat způsobí změnu v indexech
    • databáze jsou různě chytré/hloupé při optimalizacích
    • indexy pomáhají při čtení
    • indexy škodí při zápisu
    • někdy se hodí replikace db tak, aby db pro vyhledávání byla důsledněji indexovaná než ta pro zápis
  • chybným nastavením JDBC poolu
    • default lock timeout
    • velikosti bufferů
    • různé optimalizace
    • rozdělení datových zdrojů podle použití (exporty vs. CRUD)
  • chybným nastavením:
    • stmt.setQueryTimeout
    • stmt.setMaxRows
    • stmt.setFetchSize
    • conn.setTransactionIsolation
    • conn.setResultSetConcurrency
    • conn.setHoldability
JPA samozřejmě k relační db přistupují přes jdbc, ale pozor!
  • JDBC transakce není nutně pod JPA transakcí a už vůbec nejsou svázané 1:1
  • JPA transakce není JTA transakce
  • můžou. Je to záležitost nastavení "persistence unit" a také nastavení hintů (viz Query.setHint)
  • EntityManager.unwrap(Connection.class) znamená spuštění JDBC transakce a svázání 1:1 JDBC konexe a JPA manažera se vším, co to obnáší.
JTA se pak řídí hlavně anotacemi, ale pozor pozor!!!
  • pokud si nedáte pozor, můžete si připravit neskutečné magické transakční peklo
  • „requires“ je dobrý default
  • „requires new“ se někdy hodí, ale … uvědomte si, co to znamená!
  • některé posloupnosti těchto hodnot dokážou naprosto šílené věci – s kolika JPA kontexty a JDBC konexemi nakonec opravdu pracujete?
Jste programátoři, vědci, ne pistolníci z televizního divokého západu. Na riskování není čas, musíte přesně vědět, co děláte ;-)