GKrellM (GNU Krell Monitors, Wikipedie), tj. grafická aplikace pro sledování systémů a různých událostí, byla po pěti a půl letech vydána v nové verzi 2.4.0. Přehled novinek na Gitea.
Americká první dáma Melania Trumpová vydala v předvečer manželovy inaugurace vlastní kryptoměnu. Jmenuje se $Melania. Donald Trump vydal vlastní kryptoměnu $Trump den před manželkou.
GNU Project Debugger aneb GDB byl vydán ve verzi 16.1. Podrobný přehled novinek v souboru NEWS.
Po 9 týdnech vývoje od vydání Linuxu 6.12 oznámil Linus Torvalds vydání Linuxu 6.13. Přehled novinek a vylepšení na LWN.net: první a druhá polovina začleňovacího okna a Linux Kernel Newbies. Odstraněn byl souborový systém ReiserFS.
19. ledna 2038 přeteče hodnota time_t na 32bitových systémech, na vyřešení problému roku 2038 (Y2K38) tedy zbývá 13 let. Např. Debian v uplynulém roce přešel na 64bitový čas. Bernhard Wiedemann z openSUSE sdílí chyby v sestavení rozšířeného softwaru.
Byla vydána druhá opravná verze 21.2 v dubnu loňského roku vydané verze 21 multimediálního centra Kodi (dříve XBMC, Wikipedie) s kódovým označením Omega.
TikTok ve Spojených státech v sobotu večer místního času přerušil činnost. Uživatelé čínskou firmou vlastněné sociální sítě dostali zprávu, že aplikaci kvůli zákazu nelze používat. TikTok je momentálně nedostupný v obchodech s aplikacemi Google Play a App Store. Podle zákona přijatého loni a potvrzeného v pátek soudem měla platforma do dneška přerušit spojení se svou mateřskou společností ByteDance, která sídlí v Číně, nebo činnost v
… více »Wings 3D, tj. open source 3D modelovací program naprogramovaný v programovacím jazyce Erlang zaměřený na modelování pomocí subdivision a inspirovaný programy Nendo a Mirai od Izware, byl vydán v nové opravné verzi 2.4.1. Ke stažení již také ve formátu Flatpak z Flathubu.
Webový prohlížeč Dillo byl vydán ve verzi 3.2.0. Přidává podporu vzorců v SVG, obrázků ve WebP, změny velikosti stránky či možností posouvání. Nedávno oslavil 25. výročí vzniku.
Hra Mini Thief je na Steamu zdarma napořád, když aktivaci provedete do 24. ledna do 19.00 [ProtonDB].
Řešení dotazu:
DELETE FROM tabulka WHERE (user_id, den) NOT IN (SELECT user_id, den FROM docasna)
INSERT INTO tabulka (...) SELECT (...) FROM DOCASNA ON DUPLICATE ROW UPDATE tabulka.dalsidata = VALUES(Dalsidata)
DELETE FROM tbl WHERE user_id = 1234; INSERT INTO tbl (user_id, datum) SELECT 1234, '2012-04-04' UNION SELECT 1234, '2012-04-05' UNION SELECT 1234, '2012-04-09'samozrejme se pocita s tim, ze nebudes poustet N insertu z phpka, ale ze si slozis ten select uz na strane php
P.S. mohol by niekto namietat, preco tie userove zaznamy jednoducho neupdatujem, ale bolo by to podla mna narocnejsie kazdy jeden zaznam skontrolovat a nasledne updatovat alebo neupdatovat, ako ich jednoducho vsetky naraz zmazat a nasledne znovu insertnut.Dám ti dobrou radu jak postupovat při databázových optimalizacích a vyždímat maximální výkon. Připraven? "Neser se do věcí kterým nerozumíš." Neber to prosím zle, ale tvoje dobře míněná snaha má přesně opačný účinek. Takovým neustálým přerovnáváním řádků dosáhneš po čase obrovské a úplně zbytečné fragmentace. Pokud má ta tabule nějakou decentní velikost, skočíš tak že víc času strávíš zbytečným iowaitem až se natáhne jeden blok z opačného konce disku než samotným updatováním. Navíc UPDATE spojený se SELECTem má databáze šanci nějak vyoptimalizovat (MySQL má dokonce speciální syntaxi na tohle) zatímco když jí to rozdrobíš, nevymyslí nic ani ten nejvydumanější query optimizer. Může s tím být spojené i další penále kvůli přepočítávaní indexů, vytlačování horkých řádek z keší etc… Hledáš tohle tohle nebo tohle. (to už je poněkolikáté, asi si to nechám vytisknout na tričko ) Pokud nepřidáváš nové řádky, může být nejlepší taktika updatnout prostě všechno, padni komu padni. Většina databází je dost chytrá a řádky které se nemění prostě ignoruje.
Když to tak po sobě čtu, Tak bych měl i pro Tebe jednu radu. Připraven? Tvoje rada tazateli platí i Tobě.Touché… Ale já se tím řídím Doby kdy jsem ztrácel čas zkoumáním intimních detailů fungování databází už je dávno pryč. Časem jsem dospěl k tomu že 1) Databáze nepíší blbci. Dokonce ani MySQL ne 2) Většinu věcí umí DB zoptimalizovat lépe než já. Nejlepší co můžu udělat je neplést se do cesty, maximálně občas trochu napovědět. 3) Když už výjimečně udělám nějakou rádobyvyfikundovanou optimalizaci tak o pár verzí DB dál může mít nulový nebo právě opačný efekt. Nad velkými daty to samozřejmě tak jednoduché není, ale pro mrzácké tisíce uživatelů a stovky tisíc řádků o kterých mluvil Adrinko to IMO platí.
U neMVCC databází jsou většinou data uložená clustrovaná dle primárního klíče (či jiného daného indexu). V tu chvíli záznamy prostě nebudou fragmentovány…V MySQL/InnoDB se clusteruje pouze obsah primárního klíče… zbytek řádky == seek. Sklepávání řádek do stejného bloku jak píšeš může hodně pomoci, o tom žádná. Ale třeba v MySQL to vede AFAIK k zamykání celých bloků i bloků s PK. U paralelně pracující aplikace (což afaik je adrinkův případ) se mi neosvědčilo takové věci vyvádět moc často. V lepším případě to zpomaluje, v horším je MySQL schopná uhnít na deadlocku. Ale moje rada se nezakládá na takových detailech, ale naopak na tom že tyhle věci by se neměly řešit dokud to není opravdu nutné.
Poslední Tvé tvrzení IMHO není pravda (už proto, že na těch tabulkách mohou být pověšené triggery, on update current timestamp a podobná zvířátka)Však proto taky píšu že to "může" být lepší tj. že je to potřeba změřit. AFAIK pokud to nebude dobře oklíčované tak by se stejně muselo seekovat. Optimalizaci tím že se nějaký kód _nenapíše_ bych ze všech vylomenin co tu padly považoval za nejmenší ztrátu času.
UPDATE
. Všechno ostatní, co popisujete vy, jsou optimalizace, a je nesmysl dělat je dopředu. Na ně přijde řada, až zjistím, že zrovna tam je úzké místo, a pak musím zjišťovat, v čem je problém. Přičemž se rozhodně nebudu pokoušet optimalizovat podle délky příkazů a ani jen podle jejich počtu.
Ano, mé řešení je také optimalizací, ale optimalizací práce programátora.Pokud je programátor lama a neumí to napsat updatem, tak to není optimalizace času ale optimalizace na kreténa. Sorry. "Předčasná optimalizace" je pro mě snaha vnucovat DB nějaké specifiké chování, ne to že člověk neumí napsat standartní dotaz. Všechno co tu padlo (DELETE…INSERT, INSERT…ON DUPLICATE KEY…, UPDATE, REPLACE) považuji z hlediská kompetentního programátora za samozřejmé nebo snadno dohledatelné. A pro nekompetentního není ztráta času se to naučit.
Vy napíšete x-krát více kódu, nad kterým budete muset daleko více přemýšlet, jen proto, že máte dojem, že to databázi tak líp sedne (proč jinak byste ho prosazoval? protože se to tak dělá? to by byl přeci fanatismus.).Ne, my nad tím nebudeme dumat a napíšeme dotaz tak jak nejlépe vystihuje náš záměr a spolehneme se že si s tím magický stroječek poradí. Můžeš tomu říkat fanatismus Psát kód je snadné, zkoumat co s ním ta mrcha provádí a ovlivňovat to je těžké.
INSERT ... ON DUPPLICATE ...
, tam je "uživatel edituje", nebo-li uživatel upravuje, což se v SQL zapisuje jako UPDATE
. Dokonce si to i dovedu živě představit - uživatel dostane nějakou tabulku na způsob Excelu, tam má některé řádky vyplněné a upravuje je, případně může některé řádky smazat a přidat na konec nové. Úpravy řádků jsou UPDATE, mazání DELETE, přidávání INSERT. Když to takhle implementujete, bude to hezky fungovat. Když se pokusíte místo UPDATE použít DELETE+INSERT a nedomyslíte to, budou si uživatelé stěžovat, že to občas dělá hlouposti. V drtivé většině případů to v tom "Excelu" uživatel nebude dělat metodou DELETE+INSERT, protože to neodpovídá způsobu, jakým lidé pracují.
Nevím, jak jste přišel na to, že operace DELETE+INSERT bude jednodušší na naprogramování. Od uživatele dostanete sadu změn, sadu smazaných řádků a sadu přidaných řádků, takže když z toho chcete udělat váš DELETE+INSERT, musíte každou tu změnu převést na dva příkazy. To není zjednodušení.
ID Sloupec 1 Sloupec 2 1 A X smazat 2 B Y smazat 3 A Z smazat přidatUživatel tabulku zedituje
ID Sloupec 1 Sloupec 2 1 A Q 2 C L 3 smazáno D L A FData projedete a triviálně poznáte, co je UPDATE, co DELETE a co INSERT. Vy byste pak musel UPDATE překládat na dva příkazy DELETE+INSERT.
Původní sada Editace A Editace B C A C D C A E Ečí algoritmus bude mít v db na konci očekávaná data? Výsledek AADD mi teda jako terno fakt nepřijde. (tomu se částečně vyhnete, pokud budete updatovat všechny záznamy, nikoli pouze editací změněná - pak ovšem zase ztratíte všechny update, které provedla aktualizace A, takže z aktualizací ABCZ a EFGZ se stane EFGCZZ - opět horší výsledek než EFGZ mého algoritmu - uřivatel B chtěl evidetnně C odstranit). -- Tak znova: já to řeším pomocí JEDNOHO update a JEDNOHO delete, NIKOLI překládat KAŽDEJ update na jeden insert a jeden delete. To samozřejmě smysl moc nemá. Už to došlo? Proč furt polemizujete s něčim, co netvrdím. Jasně, já vím, jak to budete dělat. Jen tvrdím, že je to řádově složitější, než řešení s jedním delete a jedním insertem. Protože já ani nemusím nic projíždět a poznávat, ani nemusím řešit jak to vlastně poznávat. Pokud nesouhlasíte, tak opakuji: napište to. Bez nějakých syntaktických kontrol a takovejdlech "drobností", čistě logiku. Ale nezapomeňte do toho zahrnout případnou logiku, která musí být na straně formuláře: tzn. jak vlastně budete rozlišovat, která políčka pocházejí z databáze a která jsou nová. Já to napíšu také a porovnáme.
UPDATE table SET … WHERE id = 5 AND version = 1; UPDATE table SET … WHERE id = 13 AND version = 2; UPDATE table SET … WHERE id = 24 AND version = 1; UPDATE table SET … WHERE id = 7 AND version = 1; UPDATE table SET … WHERE id = 8 AND version = 1;Vy uděláte
DELETE FROM table WHERE id = 5 AND version = 1; INSERT INTO table VALUES (5, 2, …); DELETE FROM table WHERE id = 13 AND version = 2; INSERT INTO table VALUES (13, 3, …); DELETE FROM table WHERE id = 24 AND version = 1; INSERT INTO table VALUES (24, 2, …); DELETE FROM table WHERE id = 7 AND version = 1; INSERT INTO table VALUES (7, 2, …); DELETE FROM table WHERE id = 8 AND version = 1; INSERT INTO table VALUES (8, 2, …);Před tím budete ještě muset vypínat kontrolu cizích klíčů. Je to sice dál, zato horší cesta.
DELETE FROM tabulka WHERE userid = ? INSERT INTO tabulka() VALUES (),(),() ...Jak už to mám jinak napsat? Mám pocit, že mluvím do dubu. (úplně pominu, že jsi zcela vynechal to, že jsi ze svého řešení napsal tu snadnou část, ale to, proč je to řešení složité: tzn. jak budeš evidovat nové řádky a smazané řádky a jak je budeš editovat si nenapsal.) Ano, pokud by to bylo určeno k editaci faktur, na kterých jsou cizími klíči pověšené další záznamy, tak můj algoritmus nebude vhodný. Jenže jaksi tady se nebavíme o fakturách. Zadání bylo jasné: seznam dní, žádná závislá data. Ano, kladivo se nehodí na šroubování. (Navíc na faktury se nehodí ani ten Váš algoritmus, protože ani on neřeší race condition: u editace faktur se to prostě musí řešit s jejich naprostým vyloučením, a to nesplňuje ani jeden algoritmus. Mám pocit, že vůbec nečteš co píšu a jen vymýšlíš nějaké hypotetické blbiny nesouvisející ani s dotazem tazatele, ani s tím, co píšu, jen aby sis ospravedlnil své řešení.).
Zadání bylo jasné: seznam dní, žádná závislá data.Tohle v zadání nebylo. Vy navíc předpokládáte další podmínky – třeba jednouživatelský přístup nebo to, že záznamů bude málo a nebude potřeba stránkování. Jakmile některá z těchto podmínek přestane platit (což v reálném projektu bude nejpozději za týden), můžete vaše řešení zahodit a udělat to celé znova způsobem, který popisuju.
I ten delete může mít v IN navíc podmínky na konkrétní ID, kdybych to chtěl řešitNa tom tolik nezáleží. Navíc když chcete použít optimistické zamykání a řádky verzovat, musela by databáze podporovat IN pro vektory.
Opakuješ své argumenty dokola, aniž bys reagoval na jejich vyvrácení.Nic jste nevyvrátil. Akorát jste navrhl alternativní řešení, které je složitější a nefunguje.
Tvůj algoritmus také maže to, co nemá, a naopak nemaže to co máNapříklad?
Jde o dni, takže pokud jich bude více, budou zobrazena např. po měsících, čtvrtletích, v každém případě to bude seřazený interval, takže opět mám jednoduchý způsob, jak smazat vše v daném balíku.Akorát budete muset pro každý pohled znovu navrhovat dotaz. Bude chtít vedoucí upravovat záznamy všech podřízených? Nový dotaz. Bude chtít někdo zobrazení za pracovní dny, za svátky? Další dva dotazy. Přičemž víceuživatelský přístup jste stále nevyřešil.
Multihodnotové IN normálně databáze podporujíDatabáze normálně možná, MySQL pokud vím ne.
číslo verze přeci mohou všechny záznamy sdíletNo to bude báječné, takže kdokoli udělá nějakou změnu, všem ostatním tím způsobí konflikt.
kde je v zadání nějaké verzováníJe to klasický způsob, jak řešit optimistické zamykání.
Dokázal jsem Vám na reálném příkladěNedokázal. Napsal jste nějaký zmatený příklad, který by v praxi vůbec nebylo možné realizovat.
mimochodem, ono to ani z principu nejde - z principu prostě nezle určit, jestli současná změna jedné řádky má mít za výsledek jednu nebo dvě řádkyAle jde to. Protože změna údajů v řádku a přidání řádku jsou dvě různé operace jak z hlediska uživatele, tak z hlediska databáze. Ze změny se tedy nikdy nemůže stát přidání. Zkuste si to třeba v Excelu – úprava řádku a přidání řádku jsou dvě různé operace.
CREATE TEMPORARY TABLE a(a integer, b integer);
INSERT INTO a VALUES ( 1, 2 ) , ( 3, 4 ) , (5,6);
SELECT * FROM a WHERE (a, b) IN (( 3, 4 ), (5,6))
Sdílet, tzn. sdílet jednu sekvenci. Omlouvám se, že to nevysvětluji dosti polopatě, furt marně předpokládám, že než něco napíšeš, tak se nad tím zamyslíš.
Jenže uživatel, pokud chce jeden záznam smazat a jeden přidat, tak prostě ten "k smazání" změní na ten novej. A aplikace nemá šanci poznat, jestli to je úprava termínu (tzn. dvě takové konkurenční úpravy mají furt modifikovat jeden záznam), nebo jestli je to přidání nového a smazání starého (tzn. další úprava toho pole má generovat další záznam).
Ono to není jasné ani v realitě: když se jedna schůzka zruší a místo toho se svolá na příští týden, jde o stejnou schůzku, jen přesunutou, nebo o jinou schůzku? Když navrhuješ aplikaci, nemůžeš se na to dívat jako programátor s jasně vymezenjma kolonkama: INSERT, UPDATE. Musíš myslet jako normální lidi.
To byla jedna chyba tvého algoritmu. Druhá chyba je v tom, že současné přidání jednoho záznamu dvěma lidmi tento záznam dabluje. A poslední chyba je, že když uživatel B něco smaže, ale těsně před tím to tam uživatel B vloží (např. jen proto, že to tam bylo, ale on vloží nějakou hodnotu mezi dvě jiné, takže všem datům se změní IDčka a toto jako poslední bude nově vložené), tak přestože to A chtěl smazat a editoval poslední, tzn. má být smazáno, tak to v db zůstalo.
Zmatený příklad který nelze realizovat? Jako proč? To, že něco nechápete ještě neznamená, že to nejde realizovat. Pokud nerozumíte mému zápisu, klidně se zeptejte na konkrétní věc, co znamená, rád vysvětlím. A pokud tvrdíte, že tato posloupnost operací nelze realizovat, tak doložte proč. Napsat, že je něco blbost bez sebemenšího odůvodnění umí každý, ale ve slušné diskusi se neodůvodněné argumenty nepoužívají, takže na to radši nebudu blíže reagovat.Sdílet, tzn. sdílet jednu sekvenci. Omlouvám se, že to nevysvětluji dosti polopatě, furt marně předpokládám, že než něco napíšeš, tak se nad tím zamyslíš.Nápodobně. Popište s tou vaší sdílenou sekvencí dva případy s tabulkou, která má dva řádky. V prvním případě jeden uživatel upraví jeden záznam, ve druhém případě první uživatel upraví jeden záznam a druhý uživatel druhý záznam. Jak se změní verze?
Jenže uživatel, pokud chce jeden záznam smazat a jeden přidat, tak prostě ten "k smazání" změní na ten novej. A aplikace nemá šanci poznat, jestli to je úprava termínu (tzn. dvě takové konkurenční úpravy mají furt modifikovat jeden záznam), nebo jestli je to přidání nového a smazání starého (tzn. další úprava toho pole má generovat další záznam). Ono to není jasné ani v realitě: když se jedna schůzka zruší a místo toho se svolá na příští týden, jde o stejnou schůzku, jen přesunutou, nebo o jinou schůzku? Když navrhuješ aplikaci, nemůžeš se na to dívat jako programátor s jasně vymezenjma kolonkama: INSERT, UPDATE. Musíš myslet jako normální lidi.Výhoda právě je, že uživatel buď upraví jeden záznam, nebo jeden záznam zruší a druhý přidá. Takže nemusíte nad ničím spekulovat, a prostě v databázi uděláte přesně to, co udělal uživatel. Když uživatel v kalendáři bafne čtvereček myší a přesune ho, je to úprava, když na něj klikne, zmáčkne Delete, je to smazání, když dá "Přidat událost", je to přidání. Jak prosté.
To byla jedna chyba tvého algoritmu.To nebyla chyba mého algoritmu, nýbrž vaše minutí se s reálným světem.
Druhá chyba je v tom, že současné přidání jednoho záznamu dvěma lidmi tento záznam dabluje.To není chyba. Když dva lidé přidají po jednom záznamu, je jediný správný výsledek přidání dvou záznamů. Můžete si to vyzkoušet - když do prázdné kasičky přidáte jednu korunu a někdo druhý tam pak přidá další korunu, musí tam být na konci dvě koruny. Když tam najdete jen jednu korunu, máte vadnou kasičku.
A poslední chyba je, že když uživatel B něco smaže, ale těsně před tím to tam uživatel B vloží (např. jen proto, že to tam bylo, ale on vloží nějakou hodnotu mezi dvě jiné, takže všem datům se změní IDčka a toto jako poslední bude nově vložené), tak přestože to A chtěl smazat a editoval poslední, tzn. má být smazáno, tak to v db zůstalo.Uživatel A nemůže mazat záznam, který v databázi ještě není. Uživatel B nemůže do databáze vložit záznam, který už tam je.
takže všem datům se změní IDčkaIDčka se nemění. Kdyby se měnila, nebyla by to IDčka.
Zmatený příklad který nelze realizovat? Jako proč?Protože ten příklad je jenom míchání písmenek. Za ta písmenka nejde dosadit nic z reálného světa ani nic z databáze reprezentující reálný svět. Reálný svět se vyznačuje například tím, že každý objekt existuje právě jednou, takže třeba když držíte minci a dáváte ji do kasičky, nemůže někdo jiný tutéž minci zároveň z kasičky vyndavat. V databázi se totéž reprezentuje pomocí primárních klíčů, typicky IDček, která reprezentují daný objekt.
Jak by se změnila verze - každému novému či změněnému záznamu se jako číslo verze přiřadí další číslo ze sekvence. Při změně se zjistí, zdali číslo verze v db se shoduje s číslem verze z formuláře. Jestli je tam problém, tak prosím vysvětlit, nějak furt nechápu, kde ho vidíš?U mne problém není. Problém je ve vašem řešení hromadného smazání, protože tam s žádným porovnáním čísla verze nepočítáte.
Jenže uživatel není programátor a takhle prostě nemyslí. Ten to tam prostě nějak nabouchá a čeká, že to bude fungovat.A ono to funguje, protože ty programy fungují tak, jak jsem popsal. Vyzkoušejte si to -- zkuste třeba OpenOffice.org Calc, MS Outlook kalendář, Google Calendar, MS Excel, MS Access, OpenOffice.org Base, jakékoli účetnictví, evidenci knih, správu blogu, e-shopy...
Když dva lidi napíšou, že člověk přišel ten den do práce, tak to znamená, že tam přišel dvakrát?Když člověk nemůže přijít dvakrát za den do práce, nemá to jít do databáze zadat. Což se zařídí třeba tak, že na dvojici člověk-den udělá unikátní index. Pokud pak někdo zadá druhý příchod ve stejném dni, aplikace ho upozorní na chybu - tedy v mém řešení. Ve vašem chybu zazdí a předchozí záznam smaže.
Znovu a polopatě: v databázi je záznam A. Přijde uživatel změní ho na B, pak si ale uvědomí, že vůbec nechtěl A smazat, že to bylo omylem, že chtěl jen přidat B. Tak za to ještě dopíše A. Tzn. Ačku se změní Idčko. (Nebo to tak udělá proto, že postupně po řádcích do programu opisuje termíny z diáře.) Jenže v tu chvíli jiný uživatel v současné editaci to A smaže. Ale ouha, ono tam to A furt je. Můžeš desetkrát tvrdit, že to ten uživatel udělal špatně, ale takhle se v realitě užívaci chovaj a pokud to nebudeš ve svejch aplikacích respektovat, tak je to Tvoje chyba. Aplikace je pro uživatele, ne naopak. Uživatel nic neví o tom, že záznam má nějaký idčko nebo co je to insert a delete, uživatel prostě změní data a očekává, že jsou změněná.Mně to nevysvětlujte, já jsem vám to psal už několik komentářů zpět, že vám tam chybí verzování záznamů. Když už jste na to taky sám přišel, tak si to konečně opravte.
Pokud tvrdíš, že za písmenka nejde nic dosadit, tak prosím nefušuj do programování. Protože programování není o ničem jiném než o reprezentaci reality písmenky. K tomu fakt už není co dodat, pokud si pod těma písmenkama neumíš představit třeba záznam že dne 1.A. přišel někdo do práce.Místo těch hloupých řečí byste konečně mohl napsat, co tedy ta písmenka znamenají. Primární klíč? Nebo snad pro identifikaci dat používáte něco jiného, než primární klíč?
Jinak v reálném světě samozřejmě nejde dát jedna mince dvakrát do jedné kasičky (aniž bys ji vyňal), ale krásně jde dvakrát do programu naťukat, že sem dal jednu minci dvakrát do jedné kasičky. A Tvuj program se s tím musí umět vyrovnat a takovéto chyby (ani ne chyby, tady prostě race condition: dva lidé vidí, že to tam ještě není, tak to tam dopíšou) odstraňovat. A ten Tvůj algoritmus toho prostě není schopnej. Můj také ne, ale narozdíl od Tvého se alespoň pro uživatele chová očekávatelněji a netvrdí o sobě, že to řeší.Ale kdepak. Můj algoritmus této chybě zabrání. To jenom váš algoritmus z toho udělá guláš.
U mě problém není.Je - ale nev algoritmu. Celá tadle subdebata se vede, protože si netušil, že Mysql umí multihodnotové IN, nevěděl jsi, jak implementovat verzování pomocí jedný sdílený sekvence:
... Jak se změní verze?...a tvrdil jsi, že to verzování bude nějak působit nějaké konflikty.
No to bude báječné, takže kdokoli udělá nějakou změnu, všem ostatním tím způsobí konflikt.Jestli to tedy už netvrdíš (co takhle uznat omyl?), tak ok, tak je jasné, že verzování jde dělat v obou algoritmech(v mém přístupu není problém zkontrolovat, že všechny mazané mají správnou verzi). Jelikož i Tvůj algoritmus bez verzování se nechová v multiuser prostředí dobře (viz dál) a v obou jde verzování snadno implementovat, pak nemá smysl se o verzování bavit. Proto ho také můj algoritmus neobsahoval - narozdíl od Tebe se snažím soustředit na princip. To, že se Tvůj algoritmus bez verzování chová špatně jsem doložil na příkladech, že je nejsi schopen pochopit nebo i vymyslet sám, můj problém není (omlouvám se za sarkasmus, ale to fakt už nejde). To že tvrdíš, že když mistr i jeho zástupce napíšou dělníkovi najednou presenci, tak že je správně, že ji má dvakrát, s tím se holt polemizovat nedá. Holt jen počítej, že když takovou aplikaci napíšeš, tak Ti ten mistr dá přes hubu, až mu to bude např. blbě počítat přesčasy. Co ty písmenka znamenají? Umíš číst? Vždyť to v minulym postu píšu. Prosím už po desáté, alespoň zkus číst co jsem napsal. Tak znova: Můžeš si pod každým písmenkem např. představit datum, kdy byl daný užívák v práci. A ano, normální člověk v životě používá většinou pro identifikaci něco jiného, než primární klíč - u data např. právě to datum. To, že záznam nějakej PK má, uživatele vůbec netrápí a právě proto je CHYBA očekávat, že bude rozlišovat mezi přepsáním data a smazáním + vytvořením nového: protože tyto operace se liší právě pouze tím, jaké má výsledný záznam PK. Pokud se tedy aplikace v těchto případech chová odlišně, tak budou uživatelé na aplikaci nadávat. A Tvůj algoritmus se právě (mj.) v těchto případech (bez verzování, viz výš) nekonzistentně chová. PS: Tvůj výkřik s vyjmenováním padesáti programů, kdy každej má multiuser konkurenci vyřešenou lépe či hůře různými algoritmy (často i pštrosem) pak komentovat vůbec nebudu, nevím, co tím chtěl básník říci. A pokud Ti nestačí soupis chyb, tak tady máš další: A nějaký záznam smaže a potom B ten samý záznam (browser si otevřel před potvrzením transakce A) změní, tak ten záznam stejně zmizí Přitom B provedl akci později a tak by tam měl zůstat záznam B. A třeba zrovna toto neodstraní ani Tebou navržené verzování. PPS: Btw. - ono ani s verzováním z PRINCIPU nelze problém současné editace vyřešit. Jestli nechápeš proč, tak se zamysli, proč v databázích existuje izolace transakcí SERIALIZABLE, která právě tento problém řeší, a proč transakce na této úrovni izolace nejsou zaručeně proveditelné (tzn. mohou být zaříznuté, že nejdou serializovat).
Celá tadle subdebata se vede, protože si netušil, že Mysql umí multihodnotové INZda to umí nebo neumí je nepodstatný implementační detail. Když to nemá popsané v dokumentaci operátoru
IN
, je celkem logické myslet si, že to neumí.
nevěděl jsi, jak implementovat verzování pomocí jedný sdílený sekvenceNevěděl jsem, jak to udělat funkčně. Vaše nefunkční řešení mne nezajímá.
a tvrdil jsi, že to verzování bude nějak působit nějaké konflikty.Standardní verzování jednotlivých řádků, které jsem použil, problémy způsobovat nebude. Problémy bude způsobovat vaše neverzování.
Jestli to tedy už netvrdíš (co takhle uznat omyl?), tak ok, tak je jasné, že verzování jde dělat v obou algoritmech(v mém přístupu není problém zkontrolovat, že všechny mazané mají správnou verzi). Jelikož i Tvůj algoritmus bez verzování se nechová v multiuser prostředí dobře (viz dál) a v obou jde verzování snadno implementovat, pak nemá smysl se o verzování bavit. Proto ho také můj algoritmus neobsahoval - narozdíl od Tebe se snažím soustředit na princip.O čem to píšete? Já jsem navrhl nějaký algoritmus s verzováním, který funguje. Vy jste navrhl algoritmus bez verzování, který nefunguje. Pak jste ho různě měnil a vycházely vám z toho nefunkční verze, až když jste jej konečně změnil na ten, který jsem já popsal hned na začátku, začalo vám to fungovat.
To že tvrdíš, že když mistr i jeho zástupce napíšou dělníkovi najednou presenci, tak že je správně, že ji má dvakrátTo se v mém algoritmu neděje. To jen ten váš vyrábí v databázi hlouposti.
Můžeš si pod každým písmenkem např. představit datum, kdy byl daný užívák v práci.V tom případě si tam nejdříve doplňte primární klíče, ať se máme o čem bavit.
A ano, normální člověk v životě používá většinou pro identifikaci něco jiného, než primární klíč - u data např. právě to datum.Normální člověk ovšem nemá problém poznat, co je jeden objekt, a co jiný, a je si jist tím, zda jsou to dva objekty nebo jeden. Dokáže ty objekty identifikovat - a primární klíč je jen způsob, jak tu identifikaci vyjádřit v databázi.
To, že záznam nějakej PK má, uživatele vůbec netrápí a právě proto je CHYBA očekávat, že bude rozlišovat mezi přepsáním data a smazáním + vytvořením nového: protože tyto operace se liší právě pouze tím, jaké má výsledný záznam PK.Chyba to není, každý normální člověk takhle přemýšlí. I malé dítě ve školce pozná rozdíl v tom, jestli mu jedno jablko vezmete a dáte mu místo něj jiné, nebo jestli do jednoho jablka kousnete.
A Tvůj algoritmus se právě (mj.) v těchto případech (bez verzování, viz výš) nekonzistentně chová.Můj algoritmus ale verzování má.
Tvůj výkřik s vyjmenováním padesáti programů, kdy každej má multiuser konkurenci vyřešenou lépe či hůře různými algoritmy (často i pštrosem) pak komentovat vůbec nebudu, nevím, co tím chtěl básník říci.To je dobře, že to nekomentujete, protože já jsem nic takového nenapsal. Pocit, že někdo v této diskusi neumí číst, máte správný. Bohužel vás ale musím zklamat, že tím dotyčným jste vy. Zkuste si přečíst ještě jednou, na co jsem reagoval.
A pokud Ti nestačí soupis chyb, tak tady máš další: A nějaký záznam smaže a potom B ten samý záznam (browser si otevřel před potvrzením transakce A) změní, tak ten záznam stejně zmizíNezmizí. B bude upozorněn, že někdo mezi tím změnil data, a dostane na výběr, jak konflikt vyřešit.
Btw. - ono ani s verzováním z PRINCIPU nelze problém současné editace vyřešit. Jestli nechápeš proč, tak se zamysli, proč v databázích existuje izolace transakcí SERIALIZABLE, která právě tento problém řeší, a proč transakce na této úrovni izolace nejsou zaručeně proveditelné (tzn. mohou být zaříznuté, že nejdou serializovat).Od někoho, kdo do teď nepochopil, jak optimistické zamykání s verzováním řádků funguje, to je opravdu vtipný komentář. Až to pochopíte, pochopíte taky, proč verzování řádků zabrání skrytému ztrácení změn.
To se v mém algoritmu neděje....protože kde tam kontroluješ, zdali daná hodnota v databázi je či ne? Nikde. Takže co zabrání tomu, když mistr a jeho zástupce najednou vložej do databáze stejnej den, aby se tam vložil? Dobře, řekněme, že opravíš i to. Pak je otázka -- jde i v přístupu s DELETE+INSERT zabezpečit podobně jednoduchým způsobem alespoň stejně tak dobře konzistenci? Aniž by jeden zápis (jak jsi také tvrdil) zablokoval celou databázi? Vzhledem k tomu, že tvrdíš
To jen ten váš vyrábí v databázi hlouposti.tak seš furt přesvědčenej, že ne. Dobře. Tak Ti dám poslední šanci. Zamysli se nad tím a napiš, jestli jde napsat. Pokud furt ne, tak Ti to verzování tady předvedu -- ale Ty uznáš, žes pitomec, žes tvrdil, že to nejde. Ooook? A já klidně uznám, že jsem pitomec, pokud takovej algoritmus napsat nedokážu. Oook? Jdeš do toho, nebo stáhneš ocas a uznáš omyl?
Normální člověk ovšem nemá problém poznat, co je jeden objekt, a co jiný, a je si jist tím, zda jsou to dva objekty nebo jedenAno, normální člověk třeba pozná, že schůzka 24.8. je schůzka 24.8. A pokud se mu program chová jednou tak a jednou jinak, protože té jedné samé schůzce nějakej blbej programátor jednou přiřadil id 1 a jednou přiřadil id 2, protože z nějakýho důvodu byl záznam o ní ze systému vymazán a znovu vložen Id je umělej identifikátor a rozhodně nevyjadřuje identitu objektů: není žádnou výjimkou, když ten samej objekt má v databázi postupně jiná ID, protože člověk záznam o něm několikrát do databáze vložil a zase smazal. Jestli je Id něčeho identifikátor, tak ZÁZNAMU O OBJEKTU. A programátor, kterej nutí uživatele, aby místo o OBJEKTU přemešleli o ZÁZNAMU O OBJEKTU je s odpuštěním vůl, protože jeho aplikace jsou neergonomický. PS: Tvůj příklad s kousnutým jabkem je opět demagogie, protože když vymažu a znovu vložím ten samý záznam, tak uživatel nemá šanci poznat, že byl smazán. U kousnutého jabka bys to poznal snad i Ty (sorry, nedalo mi). PPS: V příkladech je id záznamu určeno jeho pozicí, jak si jde snadno odvodit z výsledků dotazu.
DELETE FROM tabulka WHERE podminka AND verze NOT IN (...id_verze...)
if(počet smazaných < počet editovaných) then ROLLBACK
INSERT INTO tabulka() VALUES (data)
Problém s tím, že mažu všechno je Tvoje typická výtka: vůbec sis totiž neuvědomil, že přesně totéž dělá Tvůj algoritmus? Copak ty také neděláš update na všechny záznamy?, takže všem neměníš verzi? Nikde v Tvém algoritmu podmínku, na to, že selektíš z DB původní hodnoty a porovnáváš nevidím.
Nebo je to další zamlčená fíčura, takže si hraješ na to, jak máš jednoduchý algoritmus, ale to jen proto, že Ti kolem každýho update schází dalších deset podmínek? Pokud to je tak - opět: i já mohu stejně detekovat nezměněné záznamy a z hromadných operací je explicitně vyloučit, čím se to liší? Asi tím, že ten Tvůj algoritmus jsi psal Ty a tak tam se to samzořejmě předpokládá, zatímco když totéž nenapíše někdo jinej, je blb, že?
Porovnávej srovnatelné: primitivní přístup X primitivním, verzování X verzování a verzování s porovnáním dat X verzování s porovnáním dat. Opakuji: v tomto threadu šlo o to, zdali je lepší přístup po řádcích, nebo dávkový, pokud chceš dokázat, že mercedes je lepší než audi, protože hele, naložím ho do letadla a lítá, tak si posluž, ale prosím příště na to upozorni předem, abych věděl, že debata nemá cenu.
Todle totiž principiálně nejde řešit bez operací, která porovnává data a modifikuje jen opravdu změněné záznamy. (Akorát já, protože to dělám v dávce, tak budu mít možnost ošetřit situaci, kdy člověk dva záznamy vymění (tzn. defakto přehodí primární klíče). Jelikož uživatel o PK nic neví (tzn. např. pořadí dat dané PK nenese žádnou informaci) tak by tato operace neměla mít na výsledek algoritmu vliv.)
--
Ad 28.4. - Pokud to bude model, kdy je možno více schůzek jeden den, pak ovšem musí být ty schůzky rozlišené a tedy jde opět o jiný případ než co řešíme zde: je-li datum klíč, pak v našem případě jde o implementaci datové struktury set, zatímco v tamté multiset. A světe div se, různé datové struktury se upravují různými algoritmy. Jinými slovy, další příklad, kde jsi upravil zadání, abys dokázal svoji pravdu.
REPLACE
a je to vyřešené automaticky.
Já nikdy netvrdil, že nebudu potřebovat podmínky na verzi, jen že se to dá napsat jedním dotazem. … Stejnětak není pravda, že jsem někdy uvažoval DELETE+INSERT po jednomPoslyšte, nemohl byste si vybrat. Takhle se popřít hned v následujícím odstavci, to není hezké. Takže – budete záznamy mazat hromadným DELETEm s podmínkou bez IDček, nebo je budete mazat po jednom, tj. v podmínce budou IDčka?
jen že se to dá napsat jedním dotazemNo a co? To nikoho nezajímá.
stejně jako ty tvrdíš, že ta oprava těch X chyb, co jsem našel v Tvém algoritmuX = 0
mj. hromadný delete jde i podle idV tom případě netuším, co si představujete pod hromadným DELETEm. Já si pod tím představuju právě to, že podmínka popisuje množinu záznamů podle dat, ne podle primárních klíčů. Když to uděláte podle primárních klíčů, je to přesně to rozepsání každého UPDATU na dvojici DELETE+INSERT.
pokud tam doplním druhou intervalovou podmínku, tak to bude řádově efektivnější než X samostatných deletePokud k DELETE podle ID doplníte druhou podmínku, bude to nanejvýš pomalejší, než DELETE jen podle IDček.
Tady se snažíš dokázat že máš pravdu tím, že změníš zadání: my tady prostě závislá data nemáme (pokud ano, musel bys považovat autora dotazu za idiota, že vůbec DELETE+INSERT uvažuje - což vzhledem k tomu jak diskutuješ Ti asi nedělá problém? Tak co, považuješ autora dotazu za idiota?).Proč teda každý záznam v databázi má unikátní ID? Pokud má jít jen o tabulku, která pro uživatele eviduje seznam dnů, stačí dvojice uživatel+den, to celé v primárním klíči. Navíc pak je to obyčejná množina (set), která má jen operace přidání a smazání, aktualizace nemá smysl řešit.
Ty prostě místo toho, aby jsi se pořádně zamyslel nad tím, jaké je zadání a co píšou ostatníJá jsem se zamyslel. Ale takhle se nezamyslet, jak se to podařilo vám – nepochopit zadání, práci uživatelů, algoritmy ani sám sebe – to se jen tak někomu nepovede.
Co jeDELETE FROM tabulka WHERE podminka AND verze NOT IN (...id_verze...)
id_verze
?
Takže pokud uživatel upraví 100 záznamů a v 1 bude konflikt, hodíte mu zpátky na hlavu 100 záznamů, ať si ten konflikt najde ručně? To budete dostávat tisíce děkovných dopisů…if(počet smazaných < počet editovaných) then ROLLBACK
A protože furt píšeš, že můj algoritmus nejde použít, tak prosím:Dobře. Uživatel ukládá tyto změny:
smazáno: id=1, verze=1 id=3, verze=2 upraveno: id=2, verze=1, datum=A id=4, verze=2, datum=B přidáno: datum=C datum=DJak bude vypadat posloupnost SQL příkazů, které zavoláte? Jak budete testovat návratové hodnoty (počty změněných řádků)? Ideálně když to popíšete jako v předchozím komentáři v nějakém pseudoPL/SQL, ale s dosazenými hodnotami parametrů.
Copak ty také neděláš update na všechny záznamy?Proč bych to dělal? Dělám update na ty záznamy, které uživatel upravil. Neupravené záznamy ani uživatel nikam neodesílá, bylo by to jen plýtvání.
Opakuji: v tomto threadu šlo o to, zdali je lepší přístup po řádcích, nebo dávkovýUž jste si rozmyslel, který přístup zastáváte? V druhém odstavci jste byl pro přístup podle IDček (po řádcích), ve třetím pro dávkový…
Todle totiž principiálně nejde řešit bez operací, která porovnává data a modifikuje jen opravdu změněné záznamy.Změněné záznamy se poznají podle toho, že je uživatel změnil. Tedy přepsal nějakou hodnotu a potvrdil ji, otevřel editační režim a uložil změny nebo něco takového. Koukáním na výpis se záznamy nemění.
Ad 28.4. - Pokud to bude model, kdy je možno více schůzek jeden den, pak ovšem musí být ty schůzky rozlišené a tedy jde opět o jiný případ než co řešíme zde: je-li datum klíč, pak v našem případě jde o implementaci datové struktury set, zatímco v tamté multiset. A světe div se, různé datové struktury se upravují různými algoritmy. Jinými slovy, další příklad, kde jsi upravil zadání, abys dokázal svoji pravdu.Pokud jde o datovou strukturu set, bude unikátní index na dvojici uživatel, datum. Ale hlavně, uživatel nebude mít žádnou možnost upravovat, jenom přidávat a mazat. Protože v datové struktuře set nikdo nic upravovat nechce, a normální člověk si ani nepředstaví, co by to znamenalo.
Když to uděláte podle primárních klíčů, je to přesně to rozepsání každého UPDATU na dvojici DELETE+INSERTNení, protože relační databáze jsou dělané na hromadné změny dat. Zapsáním do jednoho dotazu se ušetří spousta času, protože velká část činností se bude muset dělat jen jednou (parsování dotazu, optimalizace, zamykání datových struktur etc...) a navíc bude moci databáze zvolit optimální plán na získání těch záznamů, než když se to dělá po jednom, čímž se dostáváme k další věci, ve které nemáš pravdu. Pokud mám delete where id IN (...) a pak delete where id in () and něco between něco and něco, tak je druhý dotaz může být (dle rozložení dat a statistik) rychlejší, protože je intervalový. Tzn. v prvním dotazu databáze neví, které jsou a pro každý udělá extra lookup do indexu. Pokud bude těch idček hodně, tak dokonce zvolí sekvenční přístup nebo nějaký hash-join. Pokud tam ovšem bude druhá intervalová podmínka tak si místo toho databáze může jedním dotazem do indexu zjistit patřičné bloky a v nich pak už jen sekvenčně zkontrolovat idčka. Pokud nevěříš, tak si to zkus na nějakejch rozumnejch datech udělat explain plánů, že jsou opravdu jiné, což ukazuje na to, že pro databázi je výhodnější to hledat dle té intervalové podmínky. Samozřejmě závisí na tom, jak velkou část z toho intervalu chci: ale to je přesně to "nech to na db". -- Proč má záznam v databázi unikátní ID? Třeba proto, aby byl jednoduchý primární klíč. A ze spousty jiných důvodů (např. standardní zpracování ORM nástroji či nástroji na generování dotazů atd. atd.). Navíc: já jsem někde psal, že tam musím mít idčka? To, že tam musím mít idčka je opět vaše projekce. Zas polemizujete sám se sebou.
Takže pokud uživatel upraví 100 záznamů a v 1 bude konflikt, hodíte mu zpátky na hlavu 100 záznamů, ať si ten konflikt najde ručně? To budete dostávat tisíce děkovných dopisů…Ano, hodím. Napíšu mu: v databázi se stala oproti editaci taková a taková změna (to vyslektím opět jedním dotazem), tyto dni zmizely, tyto se objevili. Opravdu chcete vložit těchto sto záznamů a ostatní smazat? Když uživatel pracuje s množinou záznamů, tak je neslušné ho nechat půlku množiny uložit a půlku ne. Je na něm, jestli bude řešit jen ten konflikt, nebo na ten konflikt zareaguje úpravou celé množiny, proč mám být chytřejší než on.
Co je id_verze?To už jsem psal? To musím každou věc napsat desetkrát? Id verze je id verze, tzn. číslo, které se po každé změně mění a je unikátní v db. Tedy např. je na tabulce before insert or update trigger NEW.id_verze = nextval('table_verze_seq')
Ale hlavně, uživatel nebude mít žádnou možnost upravovat, jenom přidávat a mazatTakže jen kvůli tomu, abych dostál svému programovacímu purismu, že něco je set, tak místo toho, aby když se člověk při zadávání splete, tak danou položku přepsal, tak ji musí smazat a nahrát jinou. Ještě že nevyvíjíš aplikace pro mě.
/příklad/Tak zaprvé jsem psal, že budu mít id verze sdílené, takže ten příklad nevyhovuje. Ale to je detail, protože
Neupravené záznamy ani uživatel nikam neodesílá, bylo by to jen plýtvání....jste totálně překroutil zadání. Vždyť tazatel přímo píše: "ale bolo by to podla mna narocnejsie kazdy jeden zaznam skontrolovat a nasledne updatovat alebo neupdatovat.". Takže dle zadání NEVÍTE, co bylo nebo nebylo upraveno, smazáno atd uživatel odesílá celou množinu a pokud to chcete vědět, musel byste to u každého záznamu zjistit (= skontrolovat, neumíte-li slovensky). Holt když celá vaše kritika vyplývá z toho, že si ani neumíte pořádně přečíst zadání....
Navíc: já jsem někde psal, že tam musím mít idčka? To, že tam musím mít idčka je opět vaše projekce.Pořád se tu oháníte dotazem, že je potřeba se do puntíku držet toho, co je tam napsáno, neuvažovat nic víc ani nic míň. Tak si to tam dohledejte.
To už jsem psal? To musím každou věc napsat desetkrát? Id verze je id verze, tzn. číslo, které se po každé změně mění a je unikátní v db. Tedy např. je na tabulce before insert or update trigger NEW.id_verze = nextval('table_verze_seq')Nechal jsem se unést těmi rádobyodbornými kecy, co tu máte (a které se vždy nakonec ukážou jako nesmysl), a předpokládal jsem, že jste se do toho příkladu pokusil napsat něco použitelného. Dobře, takže id_verze se přiřazuje ze sekvence pro celou tabulku při každém vytvoření a aktualizaci záznamu. Vzhledem k tomu, že záznamy vůbec nechcete aktualizovat, ale vždy mazat a vkládat znova, je to vlastně druhý primární klíč tabulky. Takže ho s dovolením můžeme škrtnout a nahradit primárním klíčem ze sekvence a zákazem updatu nad tabulkou. Takže váš příkaz můžeme nahradit za
DELETE ... WHERE podminka AND id NOT IN ()
. To pro databázi není zrovna šťastný dotaz, pokud nebudete mít složený index, bude muset načíst všechny záznamy podle podmínky, donačíst k nim IDčka z dat a ty pak proskenovat. Přitom ale víme, že podmínce vyhovovali v době načtení dat uživateli právě ty záznamy, jejichž IDčka máme. Takže dotaz můžeme změnit na DELETE ... WHERE ID IN()
. Ušetříme tím práci databázi (dostane rovnou IDčka, která si s vaším příkladem musela teprve donačíst), zpřehlednili jsme dotaz, a navíc máme univerzální příkaz, který můžeme použít pro všechny editační pohledy (nemusíme si pamatovat podmínku editačního pohledu). Nechci se chlubit, ale tenhle opravený dotaz jsem použil hned na začátku, protože je to polovina toho DELETE+INSERT.
Takže jen kvůli tomu, abych dostál svému programovacímu purismu, že něco je set, tak místo toho, aby když se člověk při zadávání splete, tak danou položku přepsal, tak ji musí smazat a nahrát jinou.Můžete mi prozradit, jak konkrétně si to UI představujete? Já bych třeba kalendářní data volil klikáním a tažením myši v kalendáři. Jak si představujete tu úpravu? To jako když kliknu omylem na 5.6.2012, vyvolám tam nějak editační režim, přepíšu datum na 7.6.2012 a uložím? Nebylo by milionkrát jednodušší a zažité kliknout na 5.6.2012 znovu, čímž se záznam ze setu vymaže, a pak kliknout na 7.6.2012, čímž se tam přidá nový záznam?
...jste totálně překroutil zadání. Vždyť tazatel přímo píše: "ale bolo by to podla mna narocnejsie kazdy jeden zaznam skontrolovat a nasledne updatovat alebo neupdatovat.". Takže dle zadání NEVÍTE, co bylo nebo nebylo upraveno, smazáno atd uživatel odesílá celou množinu a pokud to chcete vědět, musel byste to u každého záznamu zjistit (= skontrolovat, neumíte-li slovensky). Holt když celá vaše kritika vyplývá z toho, že si ani neumíte pořádně přečíst zadání....V zadání není nic o tom, zda vím, co bylo či nebylo upraveno. Když se chcete tak přesně držet zadání, tak buďte důsledný. Za druhé, pokud někdo umí perfektně formulovat zadání, v drtivé většině případů zná i odpověď. Spousta (ne-li většina) dotazů v této poradně spočívá v tom za tazatele nebo spolu s ním pořádně naformulovat zadání.
CREATE TEMPORARY TABLE bench (a integer primary key, b integer);
CREATE INDEX i ON bench(b);
DO LANGUAGE PLPGSQL $$
DECLARE R integer;
BEGIN
FOR R IN SELECT generate_series(1,10000) LOOP
INSERT INTO bench(a,b) VALUES
(r*20, r*1000);
END LOOP;
END $$;
analyze bench;
DO LANGUAGE PLPGSQL $$
DECLARE R integer;
BEGIN
FOR R IN SELECT generate_series(1,4000) LOOP
INSERT INTO bench(a,b) VALUES
(r*20+1 ,r+1),(r*20+2 ,r+2),
(r*20+3 ,r+3),(r*20+4 ,r+4),
(r*20+5 ,r+5),(r*20+6 ,r+6),
(r*20+7 ,r+7),(r*20+8 ,r+8),
(r*20+9 ,r+9),(r*20+10 ,r+10);
DELETE FROM bench WHERE a IN (r*20+1,r*20+2,r*20+3,r*20+4,r*20+5,r*20+6,r*20+7,r*20+8,r*20+9,r*20+10) AND b between r+1 and r+19;
END LOOP;
END;
$$;
DO LANGUAGE PLPGSQL $$
DECLARE R integer;
S integer;
BEGIN
FOR R IN SELECT generate_series(1,4000) LOOP
FOR S IN SELECT generate_series(1,10) LOOP
INSERT INTO bench(a,b) VALUES (r*20+s, r+s);
END LOOP;
FOR S IN SELECT generate_series(1,10) LOOP
DELETE FROM bench WHERE a=r*20+s;
END LOOP;
END LOOP;
END;
$$;
Na mém systému je to rozdíl 0.181s ku 0.620s. Tvůj "není rozdíl" je ve skutečnosti více než trojnásobný (což na pouhých deset dotazů je dost). A to ještě navíc tady je ten dotaz opravdu předkompilovaný, jak píšeš, což ovšem při normálním webovém programování nikdo nedělá a je to další práce navíc; a také odpadá komunikace s databází, což je další nezanedbatelná položka (a to nemluvím o případu, kdy databázovej stroj běží někde jinde na síti).
V zadání není nic o tom, zda vím, co bylo či nebylo upraveno.Autor dotazu tvrdí, že pokud by chtěl dělat nějakou aktivitu v závislosti na tom, jestli by byl daný řádek upraven, musel by to skontrolovat. Z toho si domyslí i průměrná opice, že to tedy neví, proč by vyvíjel nějakou aktivitu na zjištění skutečnosti, kterou zná? Nevykrucuj se. Jak by vypadalo UI je mi někde, je dané zadání, tak řeším zadání a ne své dojmy. Např. třeba jako textbox se všema dny (na opisování z nějakého výkazu IMHO naprosto ideální UI, pro člověka, co to používá denně daleko rychlejší než nějaký klikací blbiny).
...donačíst k nim IDčka...Co kdybys už konečně přestal vymešlet teorie a aspoň něco z toho, co tvrdíš, si zkusil. Aspoň bych tu nemusel vyvracet každou blbinu. Do příkazu výše si dodej na konec následující příkazy:
DO LANGUAGE PLPGSQL $$
DECLARE R integer;
BEGIN
FOR R IN SELECT generate_series(1,10000) LOOP
perform * from bench where a IN (20,40,60,80,100,120,140,160,180,200);
END LOOP;
END;
$$
DO LANGUAGE PLPGSQL $$
DECLARE R integer;
BEGIN
FOR R IN SELECT generate_series(1,10000) LOOP
perform * from bench where a IN (20,40,60,80,100,120,140,160,180,200) and b between 1000 and 10000;
END LOOP;
END;
$$
explain select * from bench where a IN (20,40,60,80,100,120,140,160,180,200);
explain select * from bench where a IN (20,40,60,80,100,120,140,160,180,200) and b between 1000 and 10000;
Výsledne čas u mne je 0.210s v případě BETWEEN oproti 0.294s v případě bez between. Takže pohádky vyprávíš hezký, ale je to evidetně jinak a to between databáze nějak využít umí. To dokládá i výpis z těch explain, který dokládaj, že když má databáze k dispozici rozumnou intervalovou podmínku, tak ji použije daleko radši než rozsypanej čaj primárního klíče.
DO LANGUAGE PLPGSQL $$ DECLARE R integer := 0; BEGIN INSERT INTO bench(a,b) VALUES (r*20+1 ,r+1),(r*20+2 ,r+2), (r*20+3 ,r+3),(r*20+4 ,r+4), (r*20+5 ,r+5),(r*20+6 ,r+6), (r*20+7 ,r+7),(r*20+8 ,r+8), (r*20+9 ,r+9),(r*20+10 ,r+10); DELETE FROM bench WHERE a IN (r*20+1,r*20+2,r*20+3,r*20+4,r*20+5,r*20+6,r*20+7,r*20+8,r*20+9,r*20+10) AND b between r+1 and r+19; END; $$; 1.478 ms 1.551 ms 1.504 ms DO LANGUAGE PLPGSQL $$ DECLARE R integer := 0; S integer; BEGIN FOR S IN SELECT generate_series(1,10) LOOP INSERT INTO bench(a,b) VALUES (r*20+s, r+s); END LOOP; FOR S IN SELECT generate_series(1,10) LOOP DELETE FROM bench WHERE a=r*20+s; END LOOP; END; $$; 1.428 ms 1.401 ms 1.396 msKdyž už vymýšlíte testy, které s reálnou aplikací mají pramálo společného, zkuste vymyslet takové, které nevyvrací vaše tvrzení. Ale oceňuju, že jste ten druhý test IN versus IN+BETWEEN napsal tak, aby se mnou popsané výhody řešení bez BETWEEN nemohly uplatnit. Byl to dobrý pokus, bohužel to nestačilo.
První důvod, proč je to co píšete nesmysle je, že postgresql index only scan umí až od verze 9.2Umožnit databázi optimalizaci není nesmysl, nezávisle na tom, zda tu optimalizaci umí už současná verze, nebo ji může umět nějaká budoucí.
To jako chcete říct, že DELETE nepotřebuje pracovat se samotnými daty?Co by DELETE s daty dělal? Přečte si je, zavzpomíná, co s nimi prožil, a teprve pak je smaže? Zkuste si na disku vytvořit dva soubory,jeden o velikosti 10 bajtů, druhý 10 GB a vyplňte je náhodnými daty. Pak zkuste ty soubory celé přečíst -- u toho velkého to bude trvat podstatně déle. Pak je zkuste oba smazat -- bude to trvat prakticky stejně dlouho.
Ne, prepared statement to zdaleka nevystihuje, právě kvůli režii při komunikaci s db.Režie komunikace s DB? V jednom případě pošlu dotaz a pak všechna data. Ve druhém případě pošlu dotaz a pak všechna data. Kde je rozdíl?
Takže co by se mělo cachovat?Kešují se například diskové operace, spousta operací se může odložit a udělat až najednou na závěr -- zápisy dat, indexy, diskové operace...
Ano: odstranil jste největší nesmysly: statistiky z databáze (a protože nekřičíte, tak asi i data z databáze).Zkuste se zamyslet nad tím, co dělají následující dva příkazy. Mohly by vám být povědomé.
DO LANGUAGE PLPGSQL $$ DECLARE R integer; BEGIN FOR R IN SELECT generate_series(1,10000) LOOP INSERT INTO bench(a,b) VALUES (r*20, r*1000); END LOOP; END $$; analyze bench;Nekřičím, protože nemíním reagovat na vaše ničím nepodložené a neopodstatněné výmysly. Já taky můžu svou argumentaci postavit na tom, že jste si ta čísla určitě vymyslel, ale to pak tahle debata bude už úplně k ničemu.
create function bnch(r integer) returns void language sql as
$$
INSERT INTO bench(a,b) VALUES
($1*20+1 ,$1+1),($1*20+2 ,$1+2),
($1*20+3 ,$1+3),($1*20+4 ,$1+4),
($1*20+5 ,$1+5),($1*20+6 ,$1+6),
($1*20+7 ,$1+7),($1*20+8 ,$1+8),
($1*20+9 ,$1+9),($1*20+10 ,$1+10);
DELETE FROM bench WHERE a IN ($1*20+1,$1*20+2,$1*20+3,$1*20+4,$1*20+5,$1*20+6,$1*20+7,$1*20+8,$1*20+9,$1*20+10) AND b between $1+1 and $1+19;
$$;
create function bnch2(r integer) returns void language sql as
$$
INSERT INTO bench(a,b) VALUES ($1*20+1, $1+1);
INSERT INTO bench(a,b) VALUES ($1*20+2, $1+2);
INSERT INTO bench(a,b) VALUES ($1*20+3, $1+3);
INSERT INTO bench(a,b) VALUES ($1*20+4, $1+4);
INSERT INTO bench(a,b) VALUES ($1*20+5, $1+5);
INSERT INTO bench(a,b) VALUES ($1*20+6, $1+6);
INSERT INTO bench(a,b) VALUES ($1*20+7, $1+7);
INSERT INTO bench(a,b) VALUES ($1*20+8, $1+8);
INSERT INTO bench(a,b) VALUES ($1*20+9, $1+9);
INSERT INTO bench(a,b) VALUES ($1*20+10, $1+10);
DELETE FROM bench WHERE a=$1*20+1;
DELETE FROM bench WHERE a=$1*20+2;
DELETE FROM bench WHERE a=$1*20+3;
DELETE FROM bench WHERE a=$1*20+4;
DELETE FROM bench WHERE a=$1*20+5;
DELETE FROM bench WHERE a=$1*20+6;
DELETE FROM bench WHERE a=$1*20+7;
DELETE FROM bench WHERE a=$1*20+8;
DELETE FROM bench WHERE a=$1*20+9;
DELETE FROM bench WHERE a=$1*20+10;
$$;
explain analyze bench(1111);
explain analyze bench(2222);
Samozřejmě čísla si měň jak chceš, vychází to +- furt stejně. Mě to vychází 1.5ms ku 1.9ms.
SQL funkce má samozřejmě režii (tadle nejde ani inlinovat), takže výslednej poměr bude značně větší, ale už takhle to dokazuje, že tam rozdíl je.
--
Ohledně dotazů s between a bez: psal jsi že vymažeš databázi, nic víc. Vycházím z toho že píšeš (a když tvrdíš takový s odpuštěním blbiny, tak pak už Tě podezřívám z každý blbosti). I když přistoupím na Tvoji pochybnou metodiku (teda promazávat db odmítám, to je fakt padlý na hlavu, výkon db stojí na tom, že si používaný data v drží v paměti) a měřil jeden dotaz, tak u mne i jeden dotaz s BETWEEN trvá kratší dobu než bez: typická doba pro BETWEEN dotaz je 0.0090ms, bez BETWEEN 0.0100ms. Ověřeno na mnoho dotazech na různé datové stránky.
V jednom máš trochu pravdu: vypadá to, že když dělám náhodné dotazy přes celou databázi, tak je sice BETWEEN rychlejší, ale má o něco větší sklony k občasnýmu zalagování. Pochopitelně, protože používá další index, kterej nemusí bejt v paměti (zkouším na vývojový konfiguraci co ji moc k dispozici nemá). Tendle delší čas se asi projevil u Tvýho testu na čerstvý databázi, kde to bude mít stejnej problém.
Jenže v typickém použití se edituje pouze malá množina aktuálních dat (kdo šahá x let zpátky?) a navíc právě ta data, která db před chviličkou načetla pro editaci. Takže správná metodika je spustit dotaz dvakrát za sebou a brát druhej čas. V tom případě mi to vyjde cca 0.033ms ku 0.055ms a naopak lagovat začne dotaz bez BETWEEN! což je opět pochopitelný, protože při druhym dotazu je ten interval dle kterýho se selektí určitě v paměti, zatímco select přes id jde hrabat do bitmapovýho indexu, kterej musí projít celej a paměťová náročnost je ve výsledku větší.
Jak jsem již psal: to, že při dotazu s BETWEEN volí databáze jinej plán, smysl prostě má, DB to nedělá pro nic za nic ale proto, že tu podmínku s BETWEEN umí s výhodou využít.
Ohledně dotazů s between a bez: psal jsi že vymažeš databázi, nic víc.Ne, nepsal. Pořád máte spoustu řečí o tom, jak mám pozorně číst - že byste si je vzal taky k srdci? Nepsal jsem o mazání databáze, ale o práci nad čistě založenou databází -- založenou posloupností 4 příkazů okopírovanou od vás. A nepsal jsem to u SELECTů s BETWEEN, ale u INSERTů a DELETEů. V případě SELECTů se totiž obsah databáze nemění, takže opakované testy lze plus mínus dělat nad stále stejnou databází. Zkuste si ty dotazy porovnat nad nějakými reálnými daty, třeba pro sto uživatelů. Za období budete mít průměrně třeba 10 záznamů. Takže dotaz podle ID najde v indexu 10 záznamů a ty načte. Dotaz podle BETWEEN najde podle indexu 1000 záznamů, ty načte a bude je sekvenčně procházet a porovnávat s ID. No, ona to ta databáze ve skutečnosti takhle dělat nebude a sestaví plán přesně opačně, tj. načte těch 10 záznamů podle ID a pak jen zkontroluje tu BETWEEN podmínku. Takže je to jen příklad předčasné optimalizace. Navíc když už se do takové optimalizace chcete pouštět, měl byste index explicitně vytvořit jako B-tree. Dnes je to sice default, ale to se může změnit, a hash index vám pro BETWEEN bude houby platný. Když už budete v tom měnění indexu, aby se neprojevil výše popsaný problém, předělejte ho rovnou na složený index, buď
user_id + datum
nebo datum + id
. Pak ta optimalizace začne dávat smysl. A taky začne být jasné, že má smysl se s ní zabývat až tehdy, když to bude úzké místo aplikace.
drop table bench ;drop table bench ;
CREATE TABLE bench
(
a integer primary key,
b integer, /*userid*/
c integer, /*den*/
constraint uniq unique(b,c)
);
insert into bench(a,b,c) select (r % 2) * 100000 + (r/2), r / 100, r % 100 from generate_series(1,100000) u(r);
analyze bench;
explain analyze select count(a) from test.bench Where a in (4475,104475,4476,104476,4477,104477,4478,104478,4479,104479)
/*AND b=89 AND c BETWEEN 50 AND 50+10*/
;
explain analyze select count(a) from test.bench Where a in (3215,103215,3216,103216,3217,103217,3218,103218,3219,103219)
/*AND b=64 AND c BETWEEN 30 AND 30+10*/
To je úplně m modelovej případ - edituju nějakej subset dní z uživatele, idčka jsou trochu rozházený. A to je těch záznamů jen deset, s vzrůstajícím počtem je intervalovej dotaz efektivnější.
Píšeš předčasná optimalizace: Takže už začínáš uznávat, že to je lepší řešení? Nebo je to jen odvádění od tématu? O tom, zdali a jak moc se to vyplatí jsem nepsal, jen jsem tvrdil, že je to rychlejší, což jsi popíral. Opět se snažíš vykroutit tím, že polemizuješ s něčím jiným, než co tvrdím.
Nicméně pokud tedy tvrdíš, že to je předčasná optimalizace, tak je evidentně výkonu dost, čili vyhovuje nejrychleji napsané řešení. Vzhledem k tomu, že jsi už tuším uznal, že mé řešení je kratší, takže to znamená, že je pro první nástřel lepší.
Teda ty už fakt nevíš, jak se z toho vymluvit. Vzhledem k tomu, že tazatel chce editovat všechny data datného uživatele (buď s omezením na dané rozmezí dat nebo ne, podle toho bude vypadat i ten dotaz a potřebný index), tak tam takovýto index bude tak jako tak. Takže opět nesmyslný argument.
1) Proč by dobře napsaná optimalizace něco zhoršovala? Jak jsem dokázal, mnou navržené optimalizace fungují. Pokud píšeš optimalizace, co nefungují....ale bolo by to podla mna narocnejsie kazdy jeden zaznam skontrolovat a nasledne updatovat alebo neupdatovat, ako ich jednoducho vsetky naraz zmazatJednoducho pro Tvojí informaci znamená jednoduše. Tazatel evidentně považuje řešení za jednodušší, akorát má obavy o výkon tohoto jednoduchého řešení:
avsak obavam sa, ci to moc nezatazi databazovy server...Takže je to přesně naopak než píšeš. Akorát si myslí, že složitější řešení (update po jednom) výkonnosti nepomůže.
Nějakej Filip Jirsák by mohl namítat, že to mám jednoduše po jednom updatovat. Jenže tam bych ještě musel kontrolovat co vlastně updatovat a ve výsledku by to bylo náročnější, než JEDNODUCHÉ smazání a znovuvložení všeho.Tazatel tedy s tím prvním jednoduše právě polemizuje, nikoli, že to tvrdí. Tzn. že na první pohled jednoduché řešení je vlastně je podle něj složitější i pomalejší. Takže fakt nevím, co jsem úmyslně vynechal. Já jsem Vás pouze odkázal na kus textu, z kterého jednoznačně plyne, že autor DELETE/INSERT algoritmus považuje za nejjednodušší a nijak jsem to extra neřešil, protože jsem opravdu nečekal, že neumíte uznat chybu ani v takhle jasné záležitosti.
Tiskni Sdílej: