Hlavní navigace

Názory k článku Buďte moderní (v SQL)

Článek je starý, nové názory již nelze přidávat.

  • 14. 6. 2016 15:45

    Ivan (neregistrovaný) 165.72.200.---

    Rekurzivni CTE jsou opravdu zvlastni. Rekl bych ze dost zasadne meni povahu SQL. Pridavaji do deklarativniho jazyka funkcionalni programovani. Prikladam jeden priklad pro Oracle:

    with t_unique( s ) as (
                    select min(t1.s)
                    from z t1
                    union all
                    select (select min(t1.s) from z t1 where t1.s>t.s)
                    from t_unique t
                    where s is not null
      )
    select * from t_unique where s is not null;

    Tohle query najde nejmensi ID z tabulky, pak samo rebe rekurzivne zavola a hleda nejmensi ID vetsi nez to predchozi. Ve vysledku dostanete stejny vysledek jako pri

    select distinct s from t1 order by 1;

    Ale mnohem rychleji (alespon v mem pripade). Pro distinct se pouzije "INDEX FAST FULL SCAN" tzn. precte se cely segmet indexu (vcetne listu) a hodnoty se nahazeji do hash tabulky. Rekuzivni CTE skace v indexu nahoru a dolu az najde vsechny naindexovane hodnoty.

    Prvni co cloveka napadne je proc to takhle Oracle nedela rovnou. Pri pohledu na explain plan vam dojde ze v pripade rekurze je planner uplne vedle a ze nedokaze predpovedet vubec nic. Pokud se s rekurznim CTE zacne prasit podobne jako se sablonami v C++ (Metaprogramming) budou muset dataabze prejit na planer jako maji VM v Prologu.

  • 15. 6. 2016 9:21

    Pavel Stěhule

    Této technice se říká loose index scan. Některé databáze jej mají implementovaný nativně - u jiných (včetně Postgresu) se musí použít workaround s CTE.

    Už několik let nabízím téma diplomové práce - implementace loose index scanu do Postgresu.

  • 15. 6. 2016 10:29

    Pavel Stěhule

    Myslím si, že by to byla hezká diplomka - seznámení se s vnitřnostmi Postgresu - optimalizace - práce se statistikami, rozšíření exekutoru. Není to ale triviální a pravděpodobně to bude i hodně pracné. Na druhou stranu - po takové diplomce se člověk dostane mezi zdejší databázovou elitu (minimálně co se týče Postgresu).

  • 15. 6. 2016 11:48

    BlackSheep (neregistrovaný) ---.homecredit.net

    Myslim, ze hezka diplomka by byla spis na tema "Kde relacni databaze selhavaji". A ty pripady tu mame, to si priznejme (pro databazisty:.... i ten vas guru Celko o tom napsal knizku)

    Celkova nenormalnost mysleni "enterprise" databazistu, kdy 90% z nich si i v roce 2016 mysli, ze staci pridat index a vono to pojede.

    Za me jsou relacni DB uplne v pohode, kdyz se pouzivaji pro ucel, ke kterymu byly vytvoreny. Tzn. transakcni operace nad nejakym (business logikou osetrenym) setem dat.

    Zbytek je nesmysl, bohuzel valna cast programatoru povazuje RDBMS za ULOZISTE dat, to neni pravda. Uloziste je uloziste a data se do nej ukladaji, s tim, ze se tak nejak neresi jak je dostat ven. Vyborne to demonstruje ten exot, co tady na rootu pise serial o relacnich databazich a je evidentni, ze nikdy realny data nevidel.

  • 15. 6. 2016 12:43

    Kokos99 (neregistrovaný) 46.30.64.---

    A co je tedy podle Vás databáze, když ne úložiště dat? Je logické, že když v té databázi nějaká data jsou, tak se jedná o úložiště dat. Pokud tohle nejste schopen pochopit, tak bych byl opatrný v tom nazývat jiné lidi exoty.

  • 15. 6. 2016 17:10

    Karel (neregistrovaný) 93.90.162.---

    Pokud potřebujete úložiště dat, tak ještě nutně nepotřebujete RDBMS. Po RDBMS sáhnete ve chvíli, kdy potřebujete, aby vám to hlídalo referenční integritu, nebo chcete data v databázi přímo zpracovávat apod. Pokud data potřebujete jen uložit a přečíst, tak existují lepší řešení než RDBMS, bez veškeré té režie na věci, které od toho nechcete.

    Přijde mi, že nechcete připustit, že mezi databází a úložistěm je implikace, nikoliv ekvivalence.

  • 15. 6. 2016 22:40

    Kokos99 (neregistrovaný) 46.30.64.---

    Pokud data potřebuji uložit a přečíst, tak stejně použiji databázi, protože na to jsou navržená. Samozřejmě pokud jste tedy těmi daty nemyslel třeba video a audio soubory a podobně.

  • 16. 6. 2016 11:14

    daniel (neregistrovaný) 193.29.76.---

    "Samozřejmě pokud jste tedy těmi daty nemyslel třeba video a audio soubory a podobně."

    Proč by nemohl být obrázek nebo video nebo hudba, do nějaké rozumné velikosti, být uloženo v DB ? Přeci to není vůbec o tom, co tam ukládám, resp. je, ale trochu jinak.
    Je to o tom, jak k tomu potřebuji přistupovat, kdo to potřebuje a co všechno od toho systému potřebuje.
    Když data potřebujete jen ukládat a pak přečíst, snad si vystačíte se syrovým FS. Proč mít zbytečně netriviální režii RDBMS ?
    Potřebujete nějak inteligentně vyhledávat, podle nějakých metadat o těch videích, oebo opravdu potřebujete ACID ? Tohle je ta přidaná hodnota databáze, ne to, že do ní lze ukládat data, to lze dneska na milion míst.

  • 16. 6. 2016 11:19

    j (neregistrovaný) 2a01:8d00:4000:----:----:----:----:----

    Relacni databaze je predevsim uloziste relaci ... to je to, co se od ni ocekava a to je to, co umi dobre. Problem je, kdyz to nekdo vyuzije jako to blbe uloziste, a relace resi v aplikaci - prevazne totalne blbe.

  • 15. 6. 2016 14:06

    Pavel Stěhule

    Pokud se relační databáze používají inteligentně, tak fungují skoro perfektně. Problém je, že se ne vždy používají inteligentně. ACID a relační model hodně věcí může zjednodušit, ale nemusí to být vždy ideální řešení, a také to není univerzální řešení. Ale to je všechno o lidech nebo o štěstí.

  • 15. 6. 2016 18:34

    Inkvizitor (neregistrovaný) 62.168.12.---

    Při vší úctě, z této odpovědi moc chytrý nejsem. Původní příspěvek byl ale samozřejmě také nekonkrétní. Možná by se hodil nějaký článek s konkrétními příklady.

  • 15. 6. 2016 19:01

    Pavel Stěhule

    Většinou, když jsou problémy s databázemi, tak jde a) o špatně navržené schéma (snaha o OOP) nebo použití EAV, b) použití nevhodné technologie na nevhodném místě (použití relační databáze jako zásobníku), použití relační databáze jako komunikačního systému, atd, c) nezvládnutí technologie poddimenzování, předimenzování, neřešení údržby, ... Všechny ty problémy primárně z neznalosti, a pak už se jen hasí.

    Opravdu jen výjimečně se setkám s tím, že by někdo řešil problém, který by se už jinde neřešil 10x. Většina těch problémů vychází z neznalosti nebo z nerespektování technologie. A v SW je to samozřejmě o to horší, že ty zásadní chyby se nedají jednoduše opravit.

    Další věcí je, že vzhledem k dnešnímu výkonu sw i hw, to paradoxně funguje i když se to voře. Teprve, když už se to hodně zvoře, tak jsou problémy (a pak už není většinou cesta zpátky). Což úplně nepřispívá ke tomu, aby vývojáři byli motivovaní se něco učit. Vždy samozřejmě existují výjimky, které potvrzují pravidlo, a znám pár firem a pár lidí, kteří se za posledních pět let hodně posunuli dopředu.

  • 16. 6. 2016 10:27

    daniel (neregistrovaný) 193.29.76.---

    "Další věcí je, že vzhledem k dnešnímu výkonu sw i hw, to paradoxně funguje i když se to voře."

    To je bohužel smutný fakt. Ono je to v ale kolikrát o to horší, že v testu je systém OK a v produkci, se zpravidla větším objemem a kvalitou dat, je to podstatně horší. A nebo to prostě funguje i na PROD do doby, než se systém přiblíží nějakému thresholdu a náhle se začne chovat sic logicky dle pravidel, tak ale hlavně jinak než doposud, což obvykle vyvolá jistou míru paniky.
    Pak člověk poslouchá nářky jako "ještě před měsícem ten dotaz bežel do 5min" ... přitom skoro každý projekt má tendenci ukládat víc a víc dat a situaci za sebou naopak moc neřešit.

  • 16. 6. 2016 11:24

    j (neregistrovaný) 2a01:8d00:4000:----:----:----:----:----

    ... prave sem asi tak milionkrat zrychlil mazani z database M$ wsus ... se nedivim ze ta jejich "udrzba" dycky padne nahubu a nikdy nedobehne ... smazani !JEDINY! aktualizace z databaze tomu trva klidne 10 minut ... lol.

  • 15. 6. 2016 15:04

    BrainLess (neregistrovaný) 178.17.6.---

    To je jednoduche "relacni db" selhavaji tam kde selze architektura ;-). Napriklad Oracle RAC je podle me jeden velky fail uz v navrhu toho jak by to melo fungovat :-)

  • 16. 6. 2016 9:27

    daniel (neregistrovaný) 193.29.76.---

    Zdravim,
    90% nenormalnich enterprise databazistu ? to je podivne vysoke cislo. A muj zkusenosti podporeny pocit je spis takovy, ze nejde o databazisty, ale spis lidi od apliakci, ktery databazim "taky rozumi".
    Dokonalym vysledkem pak je nejaky univerzalni dotaz s milionem ORu, aby to ten optimizer co mozna nejvic zmatlo. Samozrejme se ale ceka, ze DB to hrave a rychle zvladne zpracovat :)

    Tohle je ale IMHO problem nekde uplne jinde, treba ve zneuzivani jednoduchosti SQL predpokladem, ze kdyz je to tak jednoduchy, nejde to preci rozbit, resp. on si to ten optimizer nejak prebere.

    A bohuzel je to taky o tom, ze dostupnost klikacich nastroju a ruznych radcu postupne odvadi napr. DBA od toho, aby skutecne chapali, jak to uvnitr dane DB funguje; aspon u Oraclu tohle dost pocituju. Casto jsou tak DBA spokojeni, ze je jakz takz misto a jedou zalohy. Bohuzel diky tomu, ze spravuji mnoho databazi, nerozumi uz aplikaci a tuhle roli tak nejak prebira jina vrstva lidi, v horsim pripade prave tech aplikacnich.

  • 16. 6. 2016 18:59

    Pavel Stěhule

    Zjišťuju, že korporátní prostředí je hodně specifický - vlastně vůbec tam nejde o výkon, když je to ještě použitelné, ale o to, aby se hlavně nic nerozbilo. Přičemž se jedná o ohromný vlašťovčí hnízdo. Všechno je rigidně předepsané, není prostor pro kreativitu - takže, kde se tam může člověk něčemu novému naučit? Navíc se tam překvapivě tvrdě hraje o peníze - není moc prostoru pro optimalizaci - není to moc příjemné prostředí.

  • 17. 6. 2016 23:05

    Ditys

    Databázová aplikace ve větší firmě hodně připomíná výrobní linku - na začátku se cpou data, na konci vypadávají výsledky. Zadat zakázky do výroby - spočítat plán. Prostoj ve výrobě je srovnatelný s prostojem v administrativě. Co se článku týká, samozřejmě kladné hodnocení, jen mi ty ohyby SQL připadají čím dál křečovitější - ve starém Paradoxu nebo Foxce by se prostě udělal lineární výpočet přes několik přechodných tabulek s mezivýsledky a cíle by bylo dosaženo. Ty konstrukce v SQL jsou zajímavé, ale to, co jeden machr dá dohromady, těžko pochopí někdo jiný.

  • 17. 6. 2016 23:30

    Pavel Stěhule

    90% SQLek jsou ofiltrované JOINy a agregace nebo ORDER BY. Ještě ve starém ANSI SQL 99 a starším se některé úlohy nedaly řešit nebo jejich řešení bylo extrémně komplikované nebo pomalé. V novém SQL se už většina běžných úloh dá vyřešit docela čitelným zápisem (a většinou je to i dostatečně rychlé).

    Jinak v SQL se dá prasit stejně jako v čemkoliv jiném - 10 řádkovému programu v Lispu bude rozumět každý, 1000 řádkovému programu už asi jen guruové. Totéž platí i o SQLku. Nerekurzivní CTE mi může zavést aspoň nějakou štábní kulturu. Můžu si pomoct pohledy, můžu si pomoct uloženými procedurami. Primárně ale musím chtít psát čitelně - a pak nemůže mít nikdo problém s pochopením.

  • 19. 6. 2016 16:56

    Ivan Nový (neregistrovaný) 85.135.69.---

    Kdybyste se k tomu vrátil, viděl byste, jaký to byl opruz. Jakýkoliv jednodušší výběr na 20 řádků, x pomocných proměnných a nakonec někdo další co to upravuje, to taky musí nejprve pochopit. Při převodu takové databáze se to vyplatí převést po tabulkách do db, a pracovat s tím pomocí SQL.

  • 16. 6. 2016 0:28

    backup (neregistrovaný) ---.dip0.t-ipconnect.de

    ja bych mel nekolik otazek ohledne tech modernich technologii (na autora ale i na ostatni odborniky, kteri zde ctou a mohou sdelit konkretni zkusenosti)

    Aktualne jsme u toho, provest zasadni zmeny u informacniho systemu jednoho zaklaznika. Je to letite software, ktere jede se sitovou databazi a za dlouha leta provozu to umi radu veci, ktere bezne informacni systemy na trhu nedokazou - proto chce zakaznik zachovat pokud mozno vse, co system umi, ale souhlasi s prechodem na moderni databaze a programovaci prostredi.

    Dnes je mozno se rozhodnout pouze pro nejakou relacni databazi. Existuji jine exoticke systemy, ale z politickych duvodu je treba asi sahnout k temto. Stavajici system bezel bez transakci a tech ruznych integrit (30 let a kupodivu se nikdy neztratila zadna data a ani se nejak jinak neznicila) - presto se uvazuje o tom, ze se ACID pouzije a system se na to upravi -> coz je jedna z tech bolestivych zmen.

    Otazka1: Je to skutecne bezpodminecne nutne u systemu rizeny vyroby pracovat s transakcemi?

    Casto se hovori o te referencni integrite. Kdysi davno jsem zazil, jak kolegove u zakznika udelali tu integritu 'spravne' a pote se pri smazani jedne radky hledal backup, protoze se 'cascade' smazala 1/2 databaze.

    Otazka2: Je to s tou referencni integritou skutecne tak dulezite a nebo to vice prekazi nez pomaha. Opet, nejedna se o ucetnictvi ale o rizeni a pripravu vyroby. Zkusenosti z praxe vitany

    Zakaznikovi se libi free databaze (linux) v uzsim vyberu je prave Postgresql, MariaDB, MaxDB a Firebird. Zbezne jsme prohledli zakladni sql-syntax a neshledali jsme vlastne vubec zadne rozdily.
    Zde se jedna skutecne o zakladni sql-prikazy. Radi bychom totiz, kdyz uz ses tim budeme zabyvat to udelali tak, aby to bezelo s kazdou tou databazi. Storage procedury nechceme pouzivat.

    Otazka3: Odpovida to zkusenostem, je to realne?

    Jak jiz uvedeno, je informacni system plny ruznych vychytavek a zvlastnosti. Proto se jevi jako jedine schudne pouzit jednoduche sql-prikazy a zpracovani provadet v aplikacnim servru (tak je to nyni take) s tim, ze se vyuziji prapared statements. Udelali jsme si nekolik testu na takove hracce (CPU Celeron 837, HDD 2,5'' 5400 U/min)) a MariaDB s Innodb dokaze provest 10 tisic selectu za vterinu. To by nam bohate stacilo a mohli bychom jit tedy cestou jednoduchych prikazu, misto toho vsechno prekopat.

    Otazka4: Jsou zkusenosti s prepared statement skutecne takove, ze moderni databaze obdobne prikazy neparsuji a hned vyvolaji provadeci plany. Jaka je procentuelne asi to zrychleni?

    Pro rozpady kusovniku a jine rekurzivni zalezitosti by se nabizela ta CTE funkcionality - autorovo tema. U zakaznika je to tak, ze v prubehu toho rozpadu se na urcite urovni nebo podle nejakych priznaku rozhoduje, zda se ma jit ve strukture o uroven nize a nebo take ne. Zakaznik si proste vede v kusovniku u pozice prepinac, ktery rika, zda se ma v tom okamziku dale provadet rekurze a nebo zda se ma system rozpadu chovat tak, jako by uz polozka byla konecna (nakupni polozka). Jestli jsem to v clanku dobre pochopil, tak v tom prostrednim selectu u toho prikazu 'with recursion' by se neco takoveho muselo zohlednit. To mi prijde hrozne obtizne.
    Otazka5: je u tech rekurzi mozno v prubehu toho zpracovani jen za pomoci toho selectu provest nejake rozhodovani?

    U tech rekurzivnich struktur je jeste jedna takova neprijemna vec. Kdyz se ten kusovnik zapise 'nesikovne', tak se ten rozpad zacykli.
    Otazka 6: je v ramci CTE nejak osetreno to zacykleni a jak. Je uzivateli v ramci tech relacnich databazi nabidnuta nejaka podpora, aby napr. ten kusovnik nemohl zapsat 'nesikovne'

  • 16. 6. 2016 7:12

    Filip Jirsák

    Ad 1 a 2 – Podle mne to chápete špatně. Transakce nebo referenční integrita nejsou umělá omezení, která vám mají házet klacky pod nohy když modelujete reálný svět. Právě naopak, jsou to pomůcky, které vám pomáhají udělat databázový model tak, aby odpovídal reálnému světu. Třeba když přesouváte výrobek z jednoho skladu do druhého, nemůže se vám stát, že v druhém skladu se výrobek objeví, ale v prvním nezmizí – a k tomu slouží transakce, aby se ta operace (odečtení z jednoho skladu a přičtení do druhého) provedla buď celá, nebo vůbec. Podobně ta referenční integrita – to, že se vám smazala půlka databáze, svědčí o tom, že to rozhodně nebylo udělané správně. Za prvé se kaskádový delete nebo update používá jen velmi výjimečně, za druhé to zase slouží k modelování reality – takže pokud obsluha zadala, že se má něco smazat, měla se dozvědět, že na dané věci závisí to a to a to, a v tom okamžiku by si musela uvědomit, že chce mazat něco, co v realitě stále existuje.

    Ad 3 – V základní syntaxi SQL příkazů se různé databáze opravdu neliší, proto je SQL definováno jako standard. Liší se v tom, co umí navíc a jak dobře umí pracovat s daty. Pokud potřebujete jenom někam zapsat seznam záznamů a pak je zase přečíst, zvládne to perfektně i MySQL, a dokonce v tom bude lepší, než jiné databáze, protože bude rychlejší. Pokud potřebujete v jedné transakci zapsat hromadu strukturovaných navzájem provázaných údajů, další údaje z toho dopočítat a udržovat integritu dat (bohatší, než co dokáže běžná referenční integrita), MySQL vám bude k ničemu, v jednodušších případech si vystačíte s PostgreSQL, a pro složitější databázi vám stejně nezbyde nic jiného než Oracle.

    Ad 4 – MySQL opravdu není dobrá na zkoumání toho, jak se chovají moderní relační databáze. Pokud chcete databázi jenom jako hloupé úložiště záznamů a veškerou logiku chcete provádět v aplikaci, je z relačních databází MySQL/MariaDB asi nejlepší volba. Ale je otázka, zda v takovém případě je vůbec dobrou volbou relační databáze. Každopádně je pak zbytečné zkoumat do hloubky vlastnosti moderních relačních databází, protože vy je používat nechcete.

    Ad 5 – Ano, v rekurzivním dotazu se samozřejmě vyhodnocují podmínky stejně, jako v kterémkoli jiném – akorát tam máte navíc předchozí úroveň a aktuální úroveň záznamů. Ale jak už jsem psal, je otázka, zda je pro vás relační databáze dobrá volba, když píšete, že nechcete používat žádné její podstatné vlastnosti a spíš řešíte, jak ji ohnout do svého pojetí. Takhle se pracovalo několik posledních desetiletí (relační databáze byly prakticky jediné dostupné spolehlivé úložiště dat, takže všichni řešili, jak svůj model ohnout pro relační databázi), v posledních pár letech je boom No-SQL databází, které řeší právě to, že ne každý model je vhodné násilím ohýbat do relační databáze.

    Ad 6 – tohle právě řeší kontrola integrity dat v databázi. Jenže když nechcete v databázi řešit žádnou logiku a měla by jí zajišťovat jen aplikace měla by aplikace řešit i tohle.

  • 16. 6. 2016 8:32

    NooN (neregistrovaný) 217.144.16.---

    Podla toho co pisete, len dufam, ze zakaznik bude ten "inovovany" system pouzivat len pre zabavu... Alebo mu pre istoty vopred dajte Vase referencie na podobne aplikacie...

  • 16. 6. 2016 11:28

    Karel (neregistrovaný) 93.90.162.---

    1. Transakce řeší několik problémů. Ve vašem případě to mohou být tyto dva problémy: více lidí měnících si vzájemně data a problém se selháním některé z operací. Ale tady velmi záleží na tom, zda to pro vás opravdu problémy jsou. Systém se dá napsat tak, aby mu nevadilo, že si uživatelé vzájemně vidí nedokončené transakce. Stejně tak jde napsat tak, aby se vypořádal se selháním některé z dílčích operací. Například převod materiálu z lokace A na lokaci B: ponížím stav materiálu na lokaci A. Pokud to selže, tak selhala transakce. Pokud to projde, tak navýším stav materiálu na lokaci B. Pokud to selže, tak opět navýším stav materiálu na lokaci A (vrátím materiál). Transakční databáze vám v tomhle zjednoduší práci, nemusíte nic moc testovat. Pokud vám B selže, tak prostě uděláte rollback. Pokud to už ale zprogramované máte, tak cpát tam silou transakce bude zbytečná práce navíc.

    2. Referenční integrita je něco trochu jiného. Například řeknete, že v tabulce stavu skladu v poli číslo položky smí být jen taková položka, která existuje v tabulce položek. Tuto kontrolu ale můžete provádět sám, ve své aplikační logice. Pak vám referenční integrita nic moc nenabízí. Ostatně řada ERP systémů ji nepoužívá a vše kontroluje aplikační server. A co se cascade delete týká, tak to je naprostá marginalita. Nechci říkat, že se to nikdy nikde nepoužívá, ale sám jsem to použil jen na škole v semestrálce. Obecně řečeno tím říkáte, že když smažete položku, tak chcete smazat i veškeré záznamy o položce - stav skladu, historii skladových transakcí, objednávky atd. To skoro nikdy nechcete. Naopak chcete, aby vám referenční integrita oznámila, "sorry, položka už byla použita, smazat nepůjde".

    3. Jen bych uvedl, že "aby to běželo s každou" nebývá úplně triviální úloha. Ačkoliv ty databáze umí ANSI SQL, tak některé věci budete muset psát několikrát. Vybrat si dvě nebo tři je průchozí, ale ověřovat a přizpůsobovat funkci na 4+ různých databázích je hodně práce navíc.

    4. Nemám moc s čím srovnat. Osobní zkušenost mám tu, že se SQL vyplatí používat více. On SELECT dokáže poskládat data hodně efektivně. Ostatně to je jeho účel. Určitě je to lepší, než si stáhnout obsah několika tabulek do aplikačního serveru a teprve tam si začít data spojovat. A on i vhodně napsaný INSERT a UPDATE dokáže potěšit (insert into A select from B where x not in select from C). Takže třebas rozpad kusovníku děláme SELECTem.

    5. Jednotlivé databáze nabízí různé možnosti. Kolikrát silnější než ANSI SQL. Například rozpad kusovníku není v Oracle žádný velký problém, má to více řešení. Rozhodovat se to neumí, ale vy píšete ten dotaz a můžete si tam zvolit jaké podmínky chcete. Takže můžete napsat dotaz, který se na fantomech zastavuje, a jiný, který vám rozpadne i fantomy. Můžete si tam přidat podmínky na datum platnosti, nebo také ne. Neříkám, že je to triviální úloha, ale v roce 2016 to je s Oracle nebo PostgreSQL úloha efektivně řešitelná přímo v SQL.

    6. Databáze sama o sobě to kontrolovat nebude. Klidně se zacyklí. Data vrací průběžně, takže takhle můžete načíst biliony záznamů a TB dat, případně číst do nekonečna. Aby k zacyklení nedošlo si musíte zajistit sám. Možností je řada, například to konktrolovat při ukládání a záznam nedovolit uložit. To je ale těžší, než se zdá. Nebo můžete SELECT omezit na hloubku zanoření. Tedy že vám nerozpadne kusovník hlouběji než třebas do sedmé úrovně. Nebo to zajistit povahou dat - mít položky typu vyráběná, fantom a komponenta. A do kusovníku dovolit vložit jen záznamy, kde je kombinace M < F, M < K nebo F < K. Nebo omezit čtení výsledků na počet řádků (například po 1000 komponentách se zastavit s tím, že asi bude něco špatně). Kombinovat to lze s integrity reportem, který bude cíleně hledat zacyklené kusovníky a reportovat je. Možností je plno, ale databáze samotná vám nic snadného nenabídne.


    Pokud máte aplikační logiku už zprogramovanou, pak bych to pojal jen jako migraci. Je prakticky jedno na co, ale volil bych spíše PostgreSQL. Je "futureproof". Ve smyslu, že pokud jednou budete chtít od databáze něco víc, tak PostgreSQL to umí. Důležité je, že většinu věcí, co by za vás mohla řešit databáze, už vyřešených zjevně máte. Takže s transakcemi, referenční integritou apod. bych počkal až do okamžiku, kdy to budete potřebovat.

  • 16. 6. 2016 20:35

    backup (neregistrovaný) ---.dip0.t-ipconnect.de

    predne diky za odpovedi i vsem ostatnim.

    1. ja jsem nazoru, ze transakce nejsou potreba, ani kdybychom to museli psat znova. Uvazujeme o tom ale z toho duvodu, ze vseobecne je to povazovana za potrebne a vhodne (nakonec i zde v diskuzi). A bohuzel, kdyz nekdo cizi pak hovori se zakaznikem a dozvi se, ze tam transakce nejsou, tak jsem jako dodavatele ocernovani, ze problematice nerozumime. My sice muzeme na zaklade logfilu u stavajiciho systemu ukazat, ze za poslednich 15 let nemeli uzivate vubec sanci videt nedokoncenou transakci, ale kdyz kazdy prof. na univerzite je nazoru ze to musi byt, tak nemame sanci. Rozumnych nazoru jako je Vas je minumum presto diky.
    Kdyz uz jsme u toho vaseho prikladu: kdyz cast te transakce neprojde - co delate tedy krome toho rollbacku - nastartujete ji znova? - to by se vlastne melo udelat, ne? - a nebo se odsune ta odpovednost na uzivatele, at se s tim popere?

    2. Diky za to upozorneni, ze ERP systemy to nepouzivaji. Na internetu je to ale v ruznych prikladech skoro vzdy. Odhledneme od toho CASCADE, to je takovy kriklavy pripad, ktery barvite ukazuje ta mozna negativa. Mne by konkretne zajimalo napr, kdyz mate u kusovniku podminku, ze polozky musi v tabulce polozek uz existovat, jak se to dela prakticky - smite zalozit kusovnik az tehdy, kdyz jsou vsechny polozky v systemu? Nebo se pouziji nejake dummy-identifikace a pak se prepisuje?

    3. U tech databazi me tesi, ze panuje shoda, ze ty 3 databaze jsou mozne. Co by mne zajimalo je, co se skryva za tou formulaci - 'nejake veci se musi psat vicekrat'. Zkontroloval jsem datove typy - tam nejsou rozdily. CURD je take identicke. Mozna se LIMIT nekde drive lisil, ale vice mne nenapada.

    4. Na to prepare odpovedel pan Stehule dole a to je pro nas potesitelne. Je mi jasne, ze selecty, ktere dokazi na jedno parsrovani dodat rychle mnozstvi dat z ruznych tabulek maji vyhodu, ale to by melo ten dopad, ze bychom nemohli pouzit stavajici naprogramovanou logiku. To je vubec ten zasadni problem pri pouziti tech rel. databazi - jestlize mam jemnou granulitu modulu, ktere vyzaduji jen male mnozstvi dat jsou mi selecty , ktere vrati obrovske mnozstvi dat najednou k nicemu. To je ta rozdilna filozofie a my bychom se s nejakou migraci vubec nezabyvali, kdyby ty stare databaze byly jeste k mani.

    5. Diky za ty poznamky k CTE. Tohle je vec, ktera se da podle vseho od cele problematiky trochu separovat a kdyz to bude mit smysl bude to mozne pouzit. Chapu, ze v techhle vecech se bude muset asi pro kazdou databazi udelat vlastni reseni.

    6. V soucasnem systemu je to udelano podobne jak popisujete - tedy cely ten 'produkcni strom' se nachazi v binarnich stromech v pameti a vsechny zmeny v databazi se online promitnou do te pameti (tedy vsechna relevantni data). Proto je mozno po stisknuti klavesnice behem nekolika milisekund zjistit, jestli nedojde k zacykleni. A otazkou bylo, zda moderni SQL systemy neco takoveho nabizeji nebo jestli neco takoveho neexistuje jako nejaky standarni doplnek. Stavajici system se da sice pouzit, ale ten kdo to programoval uz neni k dispozici a hrabat se v tom uz nikdo nechce :-(

    Jeste jednou diky

  • 16. 6. 2016 21:34

    ehmmm (neregistrovaný) 185.99.118.---

    Ad 1, transakce: V okamziku, kdy musim psat do dvou tabulek zaroven, tak uz si to bez transakce nelajsnu. I kdyz je pravda, ze povaha vasi aplikace muze byt takova, ze to ustojite i bez transakce. A co delam po rollbacku? Zalezi dle povahy aplikace. Pokud to je neco s GUI, tak uzivateli reknu, ze se to nepovedlo a on to zkusi znova. Pokud to je nejaka sluzba na serveru, tak to sam zkusi za chvili znovu.

    Ad 2, referencni integrita: Kdyz jsem pred 15 lety brigadnicil, tak jsem taky nechapal, k cemu to tam je, vzdyt si to prece ohlida aplikace. Pak jsem parkrat daval do kupy data, protoze ma aplikace tenkrat nebyla uplne bezchybna. A kusovnik pratkicky? Asi nerozumim otazce, ale pokud chce nekdo rict, ze se nekde vyskytuje sroubek a maticka, tak prece ten sroubek a maticka uz musi v DB existovat. Pokud ale chce nekdo nadefinovat novy smontovany produkt, ve kterem je novy typ sroubku a novy typ maticky a tohle chce ulozit do DB, tak zahajim transakci, vlozim do DB novy sroubek, novou maticku, novy smontovany produkt, priradim k nemu sroubek a maticku, ukoncim transakci.

    Ad 3, rozdily mezi SQL: Jak pisete, LIMIT/TOP. Pak me takhle z hlavy napadaji ruzne NOW, CURRENT_TIMESTAMP, nekdo umi VARCHAR(MAX) a jiny pouze VARCHAR(4000)...

    Ad 5+6, kusovnik a zacykleni: Tak na neco podobneho bych napr. pouzil nejakou stored proceduru na SQL serveru. Aplikace by ji poslala produkt, ktery me zajima, procedura by chvili chrochtala a vratila by tabulku dilu, ze kterych se dany produkt sklada. Protoze neovladam techniky popsane v tomto clanku, tak bych tu proceduru proste nejak upatlal v jazyce daneho SQL serveru. Nejak bych si tam holt osetril to zacykleni. Melo by to vyhodu, ze by to bezelo na serveru, takze hodne rychle, a ze serveru ke klientovi by sel pouze vysledek. Ale jak sam pisete, evidentne uz to mate nejak poreseno v klientovi/aplikaci.

    Jak pise Karel, nejspise v prvnim kole skoncite tak, ze SQL server pouzijete pouze jako novejsi uloziste dat, ale veskera inteligence zustane v aplikaci. Takhle probihala moje prvni brigada s SQL, kdyz jsem musel predelat nejakou aplikaci ve FoxPro, aby brala data z SQL. Taky jsem to tenkrat zvladl bez transakci, referencni integrity, stored procedur... protoze jsem to proste neznal.

  • 16. 6. 2016 22:04

    Filip Jirsák

    Ad 1 – myslím, že nevíte, co to transakce jsou a k čemu slouží. Transakce nejsou nějaký bonus, který by program nějak vylepšoval. Transakce jsou způsob, jak zajistit splnění nějakých předpokladů (a existují různé druhy transakcí, které zajišťují různé předpoklady). Můžete napsat, že splnění těch předpokladů nepotřebujete, můžete napsat, že jejich splnění zajistíte jinak, než transakcemi – ale „transakce nejsou potřeba“ je nesmyslné tvrzení.

    Nechápu, jak můžete psát, že transakce nejsou potřeba a nepoužíváte je, a zároveň psát, že uživatel neviděl nedokončenou transakci. Tak používáte transakce nebo nepoužíváte? Když je nepoužíváte, uživatel nemohl vidět nedokončenou ani žádnou jinou transakci.

    Řešení, když transakce neprojde, záleží na kontextu. Někdy dává smysl zopakovat ji znovu automaticky, někdy dává smysl nechat to na uživateli, někdy nedává vůbec smysl ji opakovat a je potřeba uživateli jenom vypsat zprávu, proč není možné danou akci provést.

    Ad 2 – proč byste zakládal nějaké dummy položky a pak je přepisoval? Jak byste to dělal úplně bez databáze, bez softwaru, bez počítačů? Budete na nějakou kartu psát nějaké dummy položky a pak je přepisovat, nebo tam rovnou napíšete ty správné položky?

    Ad 3 – mají ty databáze stejnou podporu uložených procedur, funkcionálních indexů, CTE, windowing funkcí? Na CRUD a LIMIT nepotřebujete relační databázi, to zvládne i CSV soubor…

    Ad 4 – vůbec netuším, o čem to píšete. SELECT vám vrátí přesně ty záznamy a údaje, o které si řeknete. Když použijete hloupou databázi a logiku budete mít v aplikaci, budete muset z databáze tahat velké množství dat a zpracovávat je až v aplikaci. Když použijete rozumnou databázi a použijete ji správně, vrátí vám přesně jenom ta data, která uživatel potřebuje, a udělá to podstatně rychleji, než kdyby to řešila vaše aplikace.

    Ad 6 – ano, moderní SQL systémy takové věci nabízejí, dokonce i ty nemoderní. Akorát si nesmíte myslet, že SQL jsou jenom základní CRUD operace a za vrchol umění SQL považovat LIMIT.

  • 17. 6. 2016 9:46

    j (neregistrovaný) 2a01:8d00:4000:----:----:----:----:----

    ad 1) ano, podobnych veci sem videl nekolik a se 100% uspesnosti jsem vzdy (zcela uzivatelsky) zaridil nekonzitenci dat v databazi. Neni nic krasnejsiho, nez kdyz treba ze zmineneho skladu mizi zbozi kamsi do vzduchoprazdna, a to jen proto, ze se sice odepise, ale uz nepripise tam, kam ma. A zadny rollback neni, protoze tvurce prece transakce nepotrebuje.

    ad 2) ano, mnoho z nich to nepouziva, protoze vznikaly v dobe, kdy databaze == dbf. A take to podle toho vypada, klidne vam dovoli smazat hlavicky a v databazi zustanou plonkove polozky.

    ad 3) ... mozne je lecos, ale stejne se tvurce nevyhne tomu, ze co na jedne funguje, se na druhe chova "divne". Moh bych sem napastovat desikty prikladu kdy se pro ruzny databaze musi query prepsat. Sice bude delat presne totez, ale pouzije jinou syntax. Casto z naprosto neznamych duvodu - jednoduse na pohled neexistuje duvod proc by to nemelo fungovat, ale nefunguje. Pokud se zacne resit vykon, je to sranda jeste vetsi. Databaze A je vyrazne rychlejsi s joinem, databaze B se subselectem.

  • 17. 6. 2016 9:58

    hawran.diskuse

    ?
    A jak si teda zajistíte, aby sled operací, který má být atomický (buď proběhne všechno, nebo nic), takový doopravdy byl?

    PS: referenční integrita není o transakcích (jak už tu kdosi psal).

  • 17. 6. 2016 10:23

    Filip Jirsák

    Jenom bych upřesnil, že momentálně se diskutuje o atomičnosti transakcí, ale transakce relačních databází mají čtyři vlastnosti, označované jako ACID – atomicitu, konzistenci, izolovanost a trvanlivost (durability).

    Pokud Backup píše, že nepotřebuje transakce, není jasné, zda nepotřebuje žádnou těch čtyř vlastností, nebo nepotřebuje některé (jak je zajistí bez transakcí?, nebo je zajišťuje jiným způsobem (jakým?).

  • 17. 6. 2016 12:44

    podlesh

    Navíc je důležité zdůraznit, že transakce může klidně implementovat samotná aplikace, a to s takovýma vlastnostma jaké potřebuje. Což je, pokud jsem dobře pochopil, příklad toho konvertovaného systému. A celkem i věřím že to funguje, protože kdysi se tak aplikace bežně psaly.

    V případě nových aplikací je to ale otázka důvěry. Když někdo začne tvrdit že transakce nepotřebuje a napíše aplikaci zcela bez nich, tak mám šanci asi 10000:1 že je to prostě tlučhuba. Pokud vytahne ty důkazy že ta aplikace existuje a funguje bezchybně, tak dobře - patří mezi ty jedničky.

  • 17. 6. 2016 12:56

    Filip Jirsák

    Což je, pokud jsem dobře pochopil, příklad toho konvertovaného systému.
    Jsem si skoro jistý, že v takovém případě by Backup nepsal „transakce nepotřebujeme“ a jeho komentáře by nevypadaly, že moc neví, k čemu vlastně transakce slouží. Napsal by „transakce nepotřebujeme, protože máme požadavky XYZ a ty zajišťujeme pomocí ABC“.

  • 20. 6. 2016 11:45

    hawran.diskuse

    Z použití fráze "sled operací" je snad zřejmé, že se ptám na transakce ve smyslu dávky několika SQL příkazů - insert/update/de­lete (a možná nějaký ten prasoselect) - uzavřené mezí BEGIN a COMMIT, případně ten ROLLBACK.
    O vlastnostech db transakce jako takové jsem se nebavil.

    Pokud jsem špatně pochopil původní tvrzení a jsem OT, omlouvám se...

  • 20. 6. 2016 11:48

    hawran.diskuse

    Reagoval jsem na
    Filip Jirsák
    Jenom bych upřesnil, že momentálně se diskutuje o atomičnosti transakcí...

    Cífix, to odsazovaní je tak nepřehledné, :-/

  • 16. 6. 2016 11:56

    Ivan Nový (neregistrovaný) ---.ip.nej.cz

    Zkuste Odoo, je to i open source a věci, které popisujete, jsou tam řešeny, maximálně dopíšete pár vlastních modulů.

  • 16. 6. 2016 7:13

    Pavel Stěhule

    1) čemu vadí transakce - to je pomůcka pro programátora, aby nemusel řešit zámky a aby nemusel po sobě uklízet. U složitějších aplikací si nedovedu představit nepoužití transakcí.

    2) RI a další integrity jsou primárně pro programátory. Včas praští přes prsty, když někdo něco dělá jinak než bylo očekáváno. Default není CASCADE delete, ale vyhození chyby. Pokud zjistím, že nemohu nějakou operaci udělat kvůli nastaveným podmínkám, a po zralé úvaze zjistím, že ta podmínka je zbytečná, neaktuální, tak tu podmínku vyhodím. Co je důležité - po zralé úvaze. Ne, že někdo přijede do podniku, něco promaže, a pak se zjistí, že to je průser. RI integrita je nástroj, jak nemít v databázi bordel. Je jasné, že pravidla někdy omezují - když jsem nastavil constrainty v jedné aplikaci, tak obchoďáci týden frfňali, protože museli vyplňovat formuláře správně - ale další lidi už s tím neměli práci při párování, a v databázi byla data, na které se bylo spolehnout a ne snůška poznámek.

    3) určitě je možné aplikaci napsat tak, aby fungovala se všemi databázemi. Viz různé wikiny, blogy, atd. Tam, kde je databáze složitější a jsou složitější databázové operace je to pro O.S. blbost a ztráta času. Mariadb, Firebird, Postgres jsou optimalizované pro jiné use caces, a nabízejí jiné možnosti, jiné datové typy. U komerčních databází je jasné, že když někdo už zaplatil za Oracle a má na to lidi, tak bude preferovat Oracle (nebo MSSQL, ...). U O.S. databází to neplatí - navíc vzhledem minimálním nárokům na údržbu většinou o O.S. databází uživatel ani neví - takže je mu jedno, co provozuje. Navíc dneska s virtualizací už pro menší aplikace nepotřebujete ani dedikované železo.

    4) prepared statements mohou pro jednoduché a frekventované dotazy znamenat výrazné zrychlení - záleží na databázi a prostředí - minimálně 20-50%. Bacha, vždy jsou výjimky - někdy jsou pro konkrétní parametry hůře optimalizované. Ještě další zátěž jsou síťové operace, síťové latence - proto uložené procedury - jenom přepsáním kódu do uložené procedury jsem zrychlil operaci z půl hodiny na 5minut - a to to běželo lokálně. Ve storkách příkazy neběží rychleji, ale pokud se sdruží, tak odpadnou síťové latence, což u dotazů kolem pár ms může znamenat výrazné zlepšení.

    5-6) U CTE jsou techniky, jak identifikovat cykly - případně jak rekurzi omezit. A pokud by CTE poté nebylo čitelné nebo rychlé, tak minimálně v Postgresu není problém napsat funkci vracející tabulku volanou rekurzivně, kde má člověk všechno pod kontrolou. Případně je možné už při zápisu hledat cykly - a ty prostě nedovolit.

  • 20. 6. 2016 16:28

    backup (neregistrovaný) ---.dip0.t-ipconnect.de

    ...čemu vadí transakce...

    ja bych nejdrive rad upresnil tu vypoved ohledne transakci. Ta formulace znela: 'transakce nejsou potreba, ani kdybychom to museli psat znova' - vztahuje se to tedy k stavajicimu systemu, ktery se pouziva na planovani a rizeni vyroby - nejdna se tedy o zadne ucetnictvi.

    Nyni tedy k tomu, cemu transakce vadi. Ten zasadni problem by se dal popsat jako rozpor mezi modularitou a transakcnim zpracovanim. U zde uvedenych 'skolskych' prikladu to vse vypada jednoduse, ale jakmile je software modularni s tim, ze jednotlive moduly se mohou pouzit v nejruznejsich situacich nastava jednoduse receno otazka 'kam napsat begin a commit'. Diskutovat je mozno 2 takove hlavni strategie.

    1) na vstupu zpracovani se napise begin transaction , pak se vyvola ta hlavni funkce a kdyz se vrati tak se vyvola commit nebo abort. Jednotlive moduly se spolehnou na to, ze o ty transakce je postarano 'tam nahore'

    2) jednotlive moduly realizuji vlastni transakce

    Obe varianty maji pro a proti , ale v zadnem pripade ty transkce u modularniho systemu nejsou zadarmo.

  • 21. 6. 2016 7:55

    Filip Jirsák

    Pouze potvrzujete to, že nevíte, k čemu transakce slouží.

    To, že se ve vašem případě nejedná o účetnictví, vůbec nevadí. Transakce neslouží jenom pro účetnictví – transakce slouží (spolu s mnoha dalšími nástroji) k tomu, aby model, který vytváříte v počítači, odpovídal realitě. V software třeba klidně naplánujete na jeden stroj na jednu hodinu dvě různé výroby. V realitě vám to samozřejmě neprojde, ten stroj se neumí naklonovat – a transakce jsou jedním z nástrojů, který pomáhá tohle ošetřit i v tom softwaru. Nástroje pro to existují různé, lze se obejít i bez transakcí – ale pořád musíte vědět, jaký problém vlastně řešíte.

    Váš problém „kam napsat begin a commit“ je problém umělý, protože řešíte „nějaké transakce“ a ne to, k čemu ty transakce mají sloužit. Ve skutečnosti je to tak, že máte nějaké požadavky, které potřebujete splnit, a transakce je jenom nástroj, kterým to uděláte. Neřešíte, kde má být BEGIN a kde COMMIT – to plyne z reality. Naopak, to co se vám ocitne mezi BEGIN a COMMIT nazvete jednou transakcí.

    „Transakce nejsou zadarmo“ je úplně převrácený pohled. Vy nepotřebujete v systému nějaké transakce, které tam musíte draze přidávat. Vy v systému potřebujete zajistit splnění určitých předpokladů – a transakce jsou způsob, jak to snadno a levně zajistit.

    Pomohlo by vám, kdybyste na chvíli přestal používat pojem transakce a místo toho psal o tom, čeho chcete transakcemi dosáhnout. Ten váš příklad je, jako kdybyste u dvoupatrového domku řešil, kam umístíte schody. Máte dvě hlavní strategie – 1. umístit je na zahradu co nejdál od baráku, aby se daly využívat maximálně samostatně a v domě nepřekážely; 2. položit je do obýváku, protože tam budou lidé nejčastěji a ty schody se tak maximálně využijí. Jenže když přestanete řešit, kam umístit schody, a uvědomíte si, že je nějaký důvod, proč ty schody v baráku chcete mít, vzpomenete si, že vlastně potřebujete nějak propojit přízemí s prvním patrem, a k tomu právě mají sloužit ty schody – takže je logicky musíte umístit tak, že vedou z přízemí do prvního patra. Přičemž samozřejmě místo schodů můžete mít i výtah. Pokud vám ten příklad připadá absurdní – kdo by dával schody na zahradu nebo naležato, když potřebuje propojit přízemí s patrem – vězte, že stejně absurdní připadají mně vaše popisy transakcí. Přestaňte řešit, kam umístíte schody, a vraťte se k tomu, že potřebujete propojit přízemí s patrem – a přestaňte řešit transakce, a vraťte se k tomu, co jste transakcemi chtěl řešit.

  • 21. 6. 2016 10:52

    Ivan (neregistrovaný) 165.72.200.---

    Mate pravdu v tom, ze transakce se do modularniho systemu vkladaji tezko. Napr. Java EE to resi pomoci anotaci, ktere rikaji v jakem stavu musi byt transakce kdyz se metoda vola. Cele se to resi pres "paralelni zasobnik" ve kterem si JEE udrzuje stav aktualni transakce. Ani tohle reseni mi ale neprijde idealni. Ono vlastne ani zadne idenalni reseni neexistuje. Jsou to dva svety ktere jde tezko zkoubit.

    Tansakce ale v zadnem pripade nejsou cil, ktereho by bylo potreba dosahnout. Cilem je zajisteni konzistence dat. V praxi se ukazuje, ze prave tento prostredek (transakce) jsou tim nejlevnejsim zkusobem jak toho dosahnout.

    Napr. VMware Websphere transakce nepouziva. Je to napsane v Jave a pouzive to Autocommit. Kdyz to spadne, tak to zanecha dat v databazi v nekonzistentnim stavu a pri kazdem startu si to musi samo kozistenci dat samo zkontrolovat a opravit. To se bohuzel pokazde nepovede a vede to ke spouste neresitelnych problemu.

    A ted se dostavam zpet k tem transakcim, pokud je nepouzijete, tak musite sam implementovat nastroje na kontrolu konzistence dat. A to je fura prace.

  • 21. 6. 2016 11:52

    Filip Jirsák

    Cilem je zajisteni konzistence dat.
    Cílem transakcí je atomičnost změn, konzistence dat, izolovanost změn a trvanlivost změn (ACID). Pokud by vám stačila konzistence dat, nepotřebujete plnohodnotné ACID transakce.

  • 20. 6. 2016 21:28

    ehmmm (neregistrovaný) 185.99.118.---

    Tak konecne jsem si to v klidu precetl. Dekuji za clanek.

    Priznam se, ze rekurze jsem preskocil.

    Window funkce i lateral join se mi velmi libi. Otazka je, jak moc to je podporovano i v jinych serverech. Z tech vetsich me zajima MSSQL a Oracle. Z tech mensich Firebird a MySQL.

    A pak kacirsky dotaz: Pokud resim podobny problem a neovladam SQL na takove urovni (proste jsem ja nebo server 100 let za opicema), nedosahnu podobne vykonnosti, kdyz si napisu nejakou stored proceduru/funkci, ktera proleze okresy a ke kazdemu ty tri nejvetsi obce proste najde, cele to slepi dohromady a vrati? Bude to tedy na vic radku kodu, ale o tolik horsi by to byt nemuselo. Cas bych tipoval nekde mezi window funkci a lateral joinem. A hlavne to dokazu na temer jakekoliv verzi temer jakehokoliv serveru.

    (Jeste varianta kacirskeho reseni: Nedelat pro kazdy okres samostatny select na 3 nejvetsi obce, ale proste obce seradit podle okresu a velikosti, sekvence je projit a brat pouze prvni tri z kazdeho okresu.)

  • 21. 6. 2016 19:13

    Pavel Stěhule

    Všechny komerční servery už mají window funkce, LATERAL má určitě Oracle. Tuším, že podpora window funkcí už je i v trojkovém Firebirdu.
    Jinak samozřejmě, že v uložených procedurách, pokud je jazyk dostatečně, silný uděláte cokoliv. Pro pár tisíc řádků se to v rychlosti vůbec nepozná. Na druhou stranu, uložená procedura je konečná pro optimalizátor, který nebude tušit jestli výsledkem je jeden nebo 100000 řádků.
    A do třetice. Vaše navrhované řešení je ekvivalent window funkce. Cčková nativní implementace ale bude rychlejší než iterace po řádku v uložených procedurách. Samozřejmě, že je vždy otázkou o kolik, a jak je to pro dané použití významné. Pokud na 10K řádcích ušetřím 100ms, a vždy budu mít max 10K řádků, tak to asi můžu udělat skrz uložené procedury a dál neřešit.
    Na druhou stranu vždy je dobré mít znalosti SQL - uložené procedury by měly fungovat jako lepidlo efektivních SQL příkazů - nikoliv suplovat neznalosti vývojáře.

  • 21. 6. 2016 17:00

    Michal M (neregistrovaný) 81.19.14.---

    K funkcii rank() - správnejšia by myslím bola funkcia row_number().
    V testovacích dátach možno bude každá obec mať unikátny počet obyvateľov. Vtedy rank() bude dávať rovnaké poradia ako row_number(), ale pri iných testovacích dátach by rank() mohol vybrať viac obcí, než tri. Možno to niekomu znie ako zbytočné "rýpanie". Ale tým menej zbehlým v SQL window funkciách to takto môže (intuitívne) pripadať, že rank() im poradie určuje unikátne, a môžu byť nechcene uvedený do omylu.

  • 21. 6. 2016 17:04

    Michal M (neregistrovaný) 81.19.14.---

    Na konci samozrejme oprava hrubky (nejde mi to editovať): ... ovedení do omylu (keď už som použil množné číslo).

  • 22. 6. 2016 9:16

    NooN (neregistrovaný) 217.144.16.---

    Nemate pravdu, v pripade ze su v okrese napr. 4 obce s rovnakym poctom ktory je zaroven najvacsii v okrese, tak vam vyberie 4 zaznamy (namiesto 3), pretoze rank pre vsetky 4 obce je 1.

  • 22. 6. 2016 17:06

    Pavel Stěhule

    To také považuji za správné (sémanticky) - jak byste preferoval jednu obec před druhou. Otázka druhá je vlastní zobrazení, kde by to muselo být ošetřeno dynamicky.

  • 23. 6. 2016 8:45

    NooN (neregistrovaný) 217.144.16.---

    A ide o to ze vysledny pocet moze byt dolezity, ze v ziadnom pripade ich nemoze byt viac ako 3.
    Mozu byt dalsie kriteria, napr. skorsi datum dosiahnutia daného poctu obyvatelov a v tom pripade rank nepomaha. Takze ako som pisal, je to uhol pohladu a brat rank ako jedine spravne riesenie je nekorektne.

  • 23. 6. 2016 12:32

    Michal M (neregistrovaný) 81.19.14.---

    Najprv k zadaniu úlohy:
    3 najväčšie obce - je veľmi jasné - budú to 3 obce, nie 4, nie 5, ale práve 3.
    Ak tam podľa počtu obyvateľov bude viac rovnakých, tu zadanie neupresňuje, ako medzi nimi vybrať. V príklade, ktorý som včera priložil v inom komentári som navrhol 2 postupy - môžeme to nechať vybrať "náhodne" (t.j. priorita medzi rovnako veľkými obcami nie je zaručená, resp. explicitne určená), čo je stále DOBRÉ riešenie podľa uvedeného zadania. Tiež som tam uviedol LEPŠIE riešenie - že tú prioritu som si určil explicitne, podľa id, a id som plnil abecedne.
    Stále však platí, že rank, tak ako je v článku použitý, je ZLÉ riešenie.

    Takže pre čitateľov - buďte moderní, ale zároveň riešte správne a v lepšom prípade aj explicitne i také zadania, ktoré sú neúplné. Alebo inými slovami, nedostatky zadania nie sú ospravedlnením nesprávnosti alebo nedostatkov riešenia.

    Ďalej - rank, tak ako je použitý v článku - rieši iné zadanie - aké sú obce s troma najväčšími počtami obyvateľov pre každý okres. To, že sa pri unikátnych počtoch obyvateľov (čo asi platilo pri zvolenej testovacej množine v článku) zhodujú výsledky týchto dvoch zadaní, stále nemení nič na tom, že sú to rozdielne zadania.

    No a nakoniec sa musím priznať aj k tomu, že som včera netestoval ostatné riešenia. V článku ma zaujal iba rank, keďže window funkcie používam často a veľmi rád, t.j. som moderný :) . Hlavne ma ale zaujala jeho nesprávnosť, preto som sa venoval iba tomuto riešeniu.

    Ako som už uviedol, jedno zadanie je uvedené, a iné zadanie obhajujete pri ranku. Tak som si prešiel (pre mnou zvolenú testovaciu množinu 15 obcí rozdelených do 3 okresov, včera priložený kód) aj ostatné riešenia.
    Nielen rank je zlý, je ich tam viac. Niekedy limitom obmedzujete počty obyvateľov (t.j. 3 najväčšie unikátne počty, potenciálne oveľa viac obcí), inokedy zase limitujete skutočne obce (t.j. 3 obce, potenciálne menej unikátnych počtov obyvateľov).

    A najhoršie je na tom rekurzívny dotaz, kde sa obce s neunikátnym počtom obyvateľov medzi sebou roznásobujú, takže v mojej vzorke 15 obcí je výsledkom množina 98 obcí. Síce je to asi jasné, ale predsa - porovnávať výkony dotazov, ktoré ani nespočítajú správny výsledok, nemá význam.

  • 23. 6. 2016 18:45

    Pavel Stěhule

    Tady se neshodneme. Představte si, že pět sportovců na prvním místě má stejný čas. Pravděpodobně by neocenili, kdybyste první cenu dal pouze prvnímu podle abecedy. V reálném životě tyto úlohy mají své corner cases, které řešíte různě, podle situace.

  • 24. 6. 2016 8:08

    Pavel (neregistrovaný) 130.119.13.---

    Nejen ve sportu, ale i jinde (třeba ve volbách) je v případě jinak nerozhodnutelné situace použit los. Vždyť třeba pokud by bylo zadání, že máte pro další postup vybrat dva nejlepší týmy ze skupiny, tak musíte vybrat dva i kdyby čert na koze jezdil (tedy i kdyby například všechny zápasy ve skupině skončily 0:0), protože pokud vyberete jiný počet, není možné sestavit finálové zápasy.

    Pokud dostanu zadání vybrat tři největší obce, tak buďto to vyřeším tak, že vyberu vždy tři přesně specifikovaným způsobem, nebo to hodím zadavateli na hlavu, ať to upřesní. Ale nikdy nemůžu navrhnout řešení, které v ¨"corner cases" dělá nesmysly.

  • 27. 6. 2016 17:26

    Michal M (neregistrovaný) 81.19.14.---

    V poriadku, pochopenie resp. slovnú formuláciu zadania vnímame inak.
    Čo s tým, že rôzne sql dotazy v článku, ktoré riešia rovnaké zadanie (či už zadanie chápeme jedným alebo druhým spôsobom) produkujú navzájom líšiace sa výsledky ?

  • 29. 6. 2016 7:34

    Pavel Stěhule

    Pokud máte nejednoznačnost v zadání, tak samozřejmě, výsledky mohou být v těch hraničních případech jiné. Ne, že by to nešlo - asi ve všech případech by bylo možné hraniční případy definovat, a definovat i to, co považujeme za řešení - a bylo by možné ty dotazy dotlačit do stavu, kdy budou produkovat stejné výsledky. U CTE by to asi dalo více práce. Pokud bych používal klauzuli LIMIT, tak bych musel respektovat chování, a to správné řešení nadefinovat tak, aby bylo adekvátní použití LIMITu, nebo bych nemohl LIMIT použít.

    Vůbec mi ale nešlo v tech příkladech, abych dostal vždy stejné výsledky. V těch řešeních je signifikantní průnik, ale nejsou ekvivalentní - liší se chováním, možnostmi, implementací. Jako vývojář potřebuji znát, co největší množství variací, abych se mohl rozhodnout pro jedno konkrétní, buďto na základě výkonu nebo na základě chování v hraničních případech.

    Když programuji, tak vždy pracuji s modelem reality - vždy dochází k určitému zkreslení, zjednodušení. U databází (a u výkonnostně náročných úloh) může být nezbytné být pragmatikem - a realitu ohnout o něco více, aby aplikace byla použitelná (udržovatelná). Např. při optimalizacích mám na výběr mezi deterministickou a stochastickou (GA) optimalizací. Všechno ovšem záleží na kontextu.

  • 22. 6. 2016 15:07

    Michal M (neregistrovaný) 81.19.14.---

    Skúsil som pripraviť príklad na demonštráciu toho, ako som to myslel.
    Príklad je zjednodušený, ale ilustruje pointu:

    create schema test_obce;
    
    -- drop table test_obce.okresy;
    create table test_obce.okresy
    (
      id varchar(6) primary key not null,
      nazev varchar(40) not null
    );
    
    -- drop table test_obce.obce;
    create table test_obce.obce
    (
      id integer not null primary key,
      okres_id varchar(6) not null,
      nazev varchar(40) not null,
      pocet_obyvatel integer not null
    );
    
    insert into test_obce.okresy values
      ('CZ0201', 'Benešov'),
      ('CZ0202', 'Beroun' ),
      ('CZ0203', 'Kladno' )
    ;
    
    insert into test_obce.obce values
      ( 1, 'CZ0201', 'Benešov',     10000),
      ( 2, 'CZ0201', 'Bernartice',  10000),
      ( 3, 'CZ0201', 'Bílkovice',   10000),
      ( 4, 'CZ0201', 'Blažejovice', 20000),
      ( 5, 'CZ0201', 'Borovnice',   30000),
      --
      ( 6, 'CZ0202', 'Bavoryně',    10000),
      ( 7, 'CZ0202', 'Beroun',      20000),
      ( 8, 'CZ0202', 'Běštín',      20000),
      ( 9, 'CZ0202', 'Broumy',      30000),
      (10, 'CZ0202', 'Březová',     30000),
      --
      (11, 'CZ0203', 'Běleč',       30000),
      (12, 'CZ0203', 'Běloky',      30000),
      (13, 'CZ0203', 'Beřovice',    30000),
      (14, 'CZ0203', 'Bílichov',    30000),
      (15, 'CZ0203', 'Blevice',     30000)
    ;
    
    -- porovnanie window funkcii:
    select *,
      -- rank moze opakovat rovnake poradie pre lubovolny pocet riadkov:
      rank()       over (partition by okres_id order by pocet_obyvatel desc)     as original_rank_zly,
      -- tento row_number je dobry v tom zmysle, ze zarucene kazdy vysledny riadok bude mat unikatne poradie,
      -- ale medzi riadkami s rovnakym poctom, t.j. nie su odlisitelne podla orderu - pocet_obyvatel,
      -- bude ich poradie "nahodne" - t.j. ich poradie nie je zarucene:
      row_number() over (partition by okres_id order by pocet_obyvatel desc)     as row_number_dobry,
      -- tento row_number je lepsi v tom zmysle, ze order je zadefinovany az na uroven unikatnosti v tabulke,
      -- takze medzi riadkami s rovnakym poctom je explicitne urcene poradie / priorita:
      row_number() over (partition by okres_id order by pocet_obyvatel desc, id) as row_number_lepsi
      from test_obce.obce
      order by okres_id, original_rank_zly
    ;
    
    -- demonstracia, preco rank je zly pre data,
    -- ktorych pocty obyvatel nie su unikatne v ramci porovnavanej mnoziny:
    select *
      from
      (
        select *,
          rank() over (partition by okres_id order by pocet_obyvatel desc)
          from test_obce.obce
      ) s
      where rank <= 3
    ;
    -- tu si vsimnite, ze aj pocetnost je rozne zla
    -- (raz 5 zaznamov pre okres, inokedy 4 zaznamy pre okres),
    -- prave preto ze zavisi od testovacich dat
    
    -- demonstracia, preco row_number je dobry zarucene, bez ohladu na unikatnost dat:
    select *
      from
      (
        select *,
          row_number() over (partition by okres_id order by pocet_obyvatel desc)
          from test_obce.obce
      ) s
      where row_number <= 3
    ;
    -- spravny pocet zaznamov bez ohladu na obsah testovacich dat,
    
    -- a ak medzi tymi, ktore maju rovnaky pocet obyvatelov,
    -- chceme mat presne definovany order,
    -- t.j. nie "nahodny", tak vo vnutri row_number zadefinujeme
    -- zarucene unikatny order az na uroven zaznamu:
    select *
      from
      (
        select *,
          row_number() over (partition by okres_id order by pocet_obyvatel desc, id)
          from test_obce.obce
      ) s
      where row_number <= 3
    ;
    
    -- drop schema test_obce;