zacnu poslednimi, protoze v hloubi duse doufam, jak budu oznacen za neznaleho :)
fulltextove indexy nelze pouzivat v ramci innodb tabulek – tim jde do kytek transakcni bezpecnost a vykon v ramci jednoho systemu. Obejit to prirozene jde, ale …
v tomhle se zda byt i manual neuprosny
Full-text indexes can be used only with MyISAM tables, and can be created only for CHAR, VARCHAR, or TEXT columns.
nazvyTabulek a nazvySloupcu – osobne velmi durazne! varuji pred pojmenovanim velbloudi syntaxi nazevTabulky a touto syntax i v ramci pojmenovani poli. Krom toho, ze je pak vhodne si adekvatne upravit nastaveni mysql v teto veci, mysqldump na windwos (lokal) exportne strukuru a cizi klice definuje cele lowercase … „nazevpolicka“ – prestoze v tabulce je definovano jako nazevPolicka
VIEWs: bohuzel musim potvrdit dve veci – fatalni nedokonalost view a zaroven jejich pomerne zasadni nevyzpytatelnost
omlouvam se, pokud to bude znit, jako „jedna pani povidala“, ale mam zkusenost, kdy select view join dalsi data je rychly ci nepatrne rychlejsi, nez natvrdo poskladany select
v drtive vetsine pripadu je vsak vykon jakykoli select z view + dalsich dat naprosto zalostny – v ramci sveho vytizeni jsem rezignoval na zjistovani pricin a optimalizaci a proste do dotazu, ze kterych jsem si slavnostne view vypreparoval zvlast, opet sql instrukce natvrdo doplnil
ve vysledku jde dotaz, ktery je hodinami odladeny a peclive vypiplany pres explain uplne do kytek :(
COMMIT: ohledne commitu, ktery manipuluje s tabulkami – v databazi jsem si vytvoril procedury, ktere zkompletuji souvisejici data spojene „parent-child“ vazbou (ucel je veskrze nedulezity), kazdopadne pokud je tato procedura pouzita v ramci transakcniho bloku, tak celou transakci odstreli – OMG :-)
nazvyTabulek a nazvySloupcu
Doplnil bych, ze na u sloupcu nezalezi na velke/male pismeno at je server nastaven jakkoli. U tabulek to ovlivnuji dve promene:
lower_case_file_system
lower_case_table_names.
fulltextove indexy – vetsinou se dela tak ze jedna je tabulka myissam a zde je fulltextovy klic a triggrem se doplnuje z innodb tabulek.
lower_case_table_names – jak jsem naznacoval – pouzivam – beru to tak, ze co mam v my.ini/my.cnf je pro me nastaveni serveru a dle meho zrovna na nastaveni tohodle zalezi, jinak Vam pri exportu mysqlko vsechno exportne malymi pismeny
ted doufam, ze se neseknu, resil jsem to rok zpet a od te doby si proste na nektere veci davam pozor
win systemu je to tusim jedno – chova se insesitivne – problem nastane, kdyz jsem si exportnul a nahral na linuxovy server …
lower_case_file_system vidim prvne a netusim tedy, jak a jestli srovna chovani, ktere jsem popisoval – abych rekl pravdu ve finale je mi to jedno, ocekaval bych v tomhle smeru sofistikovanejsi chovani mysqlka a to v tom smeru, aby to trosku striktneji „drzelo lajnu“ – proc je jine chovani v defaultni instalaci lin/win, …
ad fulltexty – jak to obejit vim, ale uz je to mimo „transakcni bezpeci“ – ja si to omluvim i tim, ze myisam je v necem rychlejsi (asi se tim spise jen utesuji :D) … ale …
protože v mysql je více typů algoritmů: http://dev.mysql.com/…orithms.html
A jakmile použijete jen trochu složitější (view z view nebo nějaké seskupování), vždy se použije ten blbější, co vše dělá přes temptable a pracuje s mnohem více záznamy než ručně poslaný select.
Právě neschopnost MySQL nabídnout funkčně alespoň těch několik málo podporovaných vlastností mě nutí uvažovat o postgresu.
s dotazem SELECT * FROM tabulka WHERE zmeneno + INTERVAL 1 DAY >= NOW(); by mel problem i PostgreSQL – co vim tak ktera-koliv databaze. Porusuje jedno zakladni pravidlo – setkal jsem se s terminem „cisty predikat“. Za vsech okolnosti by predikaty mely byt zadavany ve forme < sloupec OPERATOR vyraz > (pokud chceme, aby se chytily indexy).
V PostgreSQL lze indexovat pouze tzv. immutable funkce – mezi nez NOW nepatri.
Nejsem databazista, takze mozna trochu hloupy dotaz: Jestli ten „vyraz“ provadi to same a v jednom pripade to dokaze udelat rychleji a efektivneji, proc to databazova masina nezoptimalizuje? U jazyku ala C/C++ je naprosto normalni, ze prekladac zvoli optimalni reseni (bud preferovana rychlost / veliksot kodu atp) za predpokladu, ze to dava stejny vysledek.
Optimalizace v db se soutřeďují na dohledání optimálního prováděcího plánu. Optimalizace samotných výrazů, alespoň co je mi známo, neexistuje. Důvod je prostý – rychlost zpracování dotazů. Pokud se nepoužíjí prepared staments, tak více-méně každý dotaz prochází stejnými etapami: parsování, transformace, generování a výběr plánu, provedení plánu. Důraz je na výběr optimálního prováděcího plánu – to má největší vliv na rychlost provedení dotazu. Optimalizace plánu je relativně náročná úloha – takže na vlastní parsování a transformace není čas. V případě SQL platí přelož, optimalizuj a zahoď (ve velké většině případů). Prepared statements případně fixované plány bohužel nejsou 100% řešení.
C/C++ má odlišný přístup – přelož, optimalizuj, ulož a volej opakovaně. Na samotnou optimalizaci je mnohem více času – a nikomu to nevadí – např. srovnejte čas překladu C a Pascalu.
Asi by bylo možné napsat kód, který by dokázal izolovat predikát – takový sw existuje – je ale dost možné, že tato samotná úloha by trvala déle než provedení zbytku dotazu. Takže zápis výrazů se nechává na inteligenci programátora – předpokládá se, že tak jednoduché pravidlo dokáže respektovat i cvičená opice – tudíž i sebeprostší kódér.
Ono je optimalizace a je optimalizace. V tomto případě se snažíme řešit úlohu přeskládání výrazu „f(x) ? g(x)“ na „x ? c“ (kde ? značí porovnání). Z analytického hlediska velmi náročná úloha a rozhodně ne něco, co by se dalo provádět při každém dotazu. Některé DB se snaží tu úlohu nějak řešit a optimalizovat alespoň to „do očí bijící“. Kupříkladu Oracle umí převádět „x ± a ? b“ na „x ? b -+ a“. To řeší nejčastější problémy s podmínkami na intervaly. Ale už jen takové „2 * x = 2“ na „x = 1“ převést neumí. Asi i to by se dalo, ale zpomalení překladu by za to nestálo.
Jednoduše řečeno, v případě DB se nejedná o optimalizaci vyhodnocení výrazu, ale o jeho převedení na formu, kdy na jedná straně bude sloupec z databáze a na té druhé konstanta.
Kupříkladu dotaz na faktury, kde je částka DPH větší než 1000 Kč:
faktury.castka_bez_DPH * 0.09 >= 1000
To znamená, že se pro každý řádek provede vynásobení hrubé částky sazbou daně a to se porovná na 1000. Optimální by ale bylo:
faktury.castka_bez_DPH >= 1000 / 0.09
Protože vpravo je konstanta a vy pak jen porovnáváte hodnotu ve sloupci s touto konstantou. Pokud je sloupec zaindexovaný, nemusíte procházet všechny řádky v tabulce.
Poznámka: uvedený příklad je samozřejmě špatně. Díky zaokrouhlovací chybě nejsou oba výrazy ekvivalentní. Pokud čásku bez DPH uvedu na stejný počet desetinných míst jako podíl 1000/0.09, nebude to fungovat. Při dvou desetinných místech viz částka 11111.11 Kč. Další důvod, proč neoptimalizovat automaticky.
„MySQL je stále mladý databázový server a otázkou je, jestli budou uvedené nedostatky v blízké budoucnosti odstraněny“
MySQL tu je skoro 15 let a pořád má problémy s naprosto základními věcmi (např. výše zmíněný fulltext vs. transakce), pořád se musí něco obcházet a ohýbat. Jak dlouho tohle chcete ještě omlouvat?
A jak dlouho je tu Oracle nebo Informix?
Mel jsem tu cest/smulu v nich nedavno neco delat, doma jsem si to nejdrive odladil na MySQL, s tim ze „co zvladne ta ‚blba‘ mysql, musi tyto opevovane DB umet taky“ .. no a neumely, ani jedna. A to to byla docela zasadni vec.
Nejde o to co to bylo, jde o to, ze nekteri lide furt odmitaji pochopit, ze kazdy umi neco. Krom toho MySQL je skutecne nejmladsi, takze se da cekat ze bude furt pozadu – ostatni nespi a stale se vyviji.
Limit fráze je velmi nestandardní. Ani nevím, jestli kromě MySQL a Postgresu ji jiná databáze podporuje. Ale silně pochybuji že ji nějaká další DB bude podporovat, když máme přenositelnou OLAP funkci rank ( row_id ), která možnosti limit výrazně převyšuje. Nutno ovšem dodat, že k OLAP funkcím se open source DB dobraly teprve nedávno ( postgress někdy v minulém roce ).
To, že v těle triggeru nemohu volat upravovat původní tabulku skrze DML mi přijde spíš jako výhoda než nevýhoda. Dost často se setkávám s tím, že programátoři si nevšimnou rozdílů mezi T-SQL a zbytem světa a triggery píší podle vzoru T-SQL. Což je samosebou špatně – v případě MySQL, PostgreSQL nebo Oraclu či DB2. V MySQL je tento přístup přímo zakázán – u ostatních databází vede k rekurzi (ve výsledku je to pomalé nebo se db chová „podivně“).
Je potřeba se MySQL v tomto případě zastat a říct, že MySQL má triggery navržené správně (v tomto ohledu – pak jsou další libůstky jako třeba práva), hlavně ovšem JINAK než MS-SQL server. MS SQL má používá primárně a pouze statement triggery, ostatní databáze row triggery – jenomže zvyk je železná košile :(.
Co tak sleduji MySQL, tak problémy s VIEW a neexistencí SIGNALu by měly být vyřešené v 5.5, která teď aktuálně vyšla. Zkoušel jí někdo?
Já vím pouze o jediném modelu, kdy v z update triggeru chci aktualizovat jiné záznamy – a tím jsou nested sets – což je Celkova implementace stromů. O žádném dalším nevím. Osobně, pokud bych zrovna nehackoval běžící aplikaci, kdy není šance psát slušný kód, bych se rekurzivně volaným triggerům vyhnul obloukem – u běžné aplikace (přestože pg s tím nemá problém). Zrovna implementace triggerů v MS Serveru – riziko rekurze, byl důvod proč se v podstatě v 90 letech docela dost zásadně nedoporučovalo používání triggerů.
V DB2 v after triggerech muzete bezproblemu upravovat jakoukoliv tabulku, klidne i tu nad kterou je trigger definovan:
CREATE TRIGGER MAJITEL.POKUSTEST AFTER INSERT ON MAJITEL.POKUS REFERENCING NEW AS NEWROW NEW_TABLE AS NTABLE FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
DELETE FROM MAJITEL.POKUS POKUS
WHERE POKUS.ID = 25;
END
proc by to mela databaze zakazovat? pro ni je trigger inline funkce jako kazda jina. db2 umi row i statement level trigery.
Psal jsem o něčem jiném. Jako hlavní riziko vidím programátory, kteří nepochopili smysl proměnných NEW a OLD, a jsou schopní napsat např. UPDATE trigger jako
BEGIN
UPDATE tab SET col = current_time
WHERE id = OLD.id;
END;
je to dost zjednodušené pro názornost.
Už jsem to psal, teď trochu jinými slovy. I když většina databází umožňuje umístit do triggerů DML příkazy – osobně se snažím spíš preferovat procedury před triggery. AFTER triggery beru primárně pouze pro kontroly (a případně jednoduché logování). Není to dáno technologickým omezením – až na MySQL většina db nemá toto omezení, jako spíš snahou nebudovat black box, kdy DML příkazem startujete nějaký monstrózní proces. Monstrózní procesy mám ráději izolované v procedurách než schované v triggerech.
„Stejné omezení platí i pro poddotazy při modifikaci záznamu – ty se také nemohou dotazovat do stejné tabulky. Takový příkaz je nutné rozdělit do dvou – nejprve získat data a v druhém kroku provést aktualizaci.“
Tohle zrovna jde, i kdyz se to musi torochu opsat
UPDATE tbl AS a INNER JOIN tbl AS b ON .... SET a.col = b.col
nebo lze upravit subquery
UPDATE tbl SET col = ( SELECT ... FROM (SELECT.... FROM) AS x);
vice http://stackoverflow.com/…-from-clause nebo http://www.xaprb.com/…et-in-mysql/
Myslím, že hodně poddotazů ve where nebo set lze přepsat do spojení.
UPDATE tabulka t, (SELECT SUM(neco) suma FROM tabulka) s SET t.sloupecek = s.suma WHERE t.id = 1
Ony vůbec ty spojení bývají v mysql jistější. Často se stane, že dokáže naplánovat
select * from tabulka where sloupec in (select max(sloupec) from tabulka)
tak, že se poddotaz vykonává pro každý řádek znovu. Proto se snažím to psát do spojení, aby na to nemohla ani pomyslet.
select t.* from tabulka t join (select max(sloupec) sloupec from tabulka) m on t.sloupec=m.sloupec
No podle mě správný řešení jsou sekvence + triger on insert (tak se to dělá např. ve firebirdu). Pokud to v aplikaci potřebuju, tak se můžu na id zeptat předem sekvence a to pak používat (je to rozhodně lepší a rychlejší než
monstra typu guid), pokud ne, chová se to jako autoinkrement.
Akorát bych bral nějakej syntaktickej curk, kterej by umoňil označit pole jako autoinkrement a vytvořil k tomu automaticky ten triger a sekvenci…
GUID prosím nééé, to je neštěstí. Blbě, dlouze se to zařazuje do indexu, nevíte co se tam dostane, kolikrát je PK delší než samotná data…
To už je lepší primární klíč dát jako int a ptát se na hodnotu z generátoru aplikace nebo si udělat vlastní mechanizmus, třeba si předrezervovat 100 hodnot a ty brát z aplikační cache, ale GUID je absolutně nejhorší řešení pro primární klíč s jakým jsem se kdy setkal, to ať si nechá a používá M$, naše chytré hlavičky vědí jak to udělat přinejhorším o trošku lépe, protože horších řešení už moc není.
Když můžete zavolat
SELECT a, b, c FROM t1; SELECT a, b FROM t2;
a dostanete dvě sady výsledků po třech a dvou sloupcích, můžete zavolat taky
INSERT INTO t1 (a, b, c, d, e) VALUES(...); INSERT INTO t2 (a, b, c, d) VALUES(...);
a za předpokladu, že t1.a, t1.b, t1.c, t2.a a t2.b jsou automaticky generované hodnoty, dostanete strukturou stejnou sadu výsledků, jako u toho selectu. Pokud to tedy podporuje ovladač databáze, knihovna atd.
Zbytečný overhead je to pro ty, co používají databázi jako skladiště dat pro PHP a relační uspořádání dat a další věci jsou jim na obtíž. Pokud někdo naopak využívá sílu relačních databází, má v databázi nadefinované kontroly, pohledy apod., ten bude chtít mít přirozeně v databázi i výchozí hodnoty. Nemusí se pak starat o to, aby každá aplikace přistupující k databázi měla nadefinované stejné výchozí hodnoty, nemusí se v každé aplikaci pachtit s tím, jak udržovat jednoznačné primární klíče, jak udržovat data konzistentní…
v databázi používam mnoho fíčur, přirozenost „chtění mít defaulty v db“ je jen váš osobní názor.
pokud mam v každý aplikaci generátor guid (nejlépe v podobě vestavěný funkce), tak je o dost levnější použít guid, než se v každý aplikaci starat o mapování „vloženejch“ dat na data skutečně uložený (sekvence v pg sou taky v pohodě, protože mam na výběr jak s nima zacházim).
defaulty (neklíčovejch atributů) můžu mít někde stranou v jednom konfiguračním souboru pro všechny aplikace.
prostě nemam rád postupy (autoincrementy, defaulty, …) o kterejch vim že mi můžou nakopat zadek
PK ID vždy jen číselná forma, v opodstatněných případech (číselníky) se dá zkousnout i nějaký krátký varchar, ale používat všude int je pohoda pro API aplikace a pro index v DB taky. Setkal jsem se s několika způsoby generování ID, autoincrement také nemám rád a mnohdy není zapotřebí, někdy je užitečný (tak v PHP), stejně tak jako default hodnoty.
Viděl jsem dost způsobů generování ID, krom autoinkrementu také pomocí „pomocné tabulky uměle vytvořených generátorů“, což mi přišlo pro PK docela zbytečné (ale pokud to v API už je třeba pro číselnou řadu objednávek, jednoduše použitelné), precachované distribuování z aplikace (vezmu hodnotu generátoru, vynásobím konstantou a mám dost IDček, až dojdou vezmu si novou sadu), to mi přišlo docela jednoduché a s plnou kontrolou co to vlastně do DB vkládám, potkal jsem i ty nešťastné GUID, taky jsem viděl SHA1 hash jako PK, dá se toho vymyslet dost, ale stejně ja paráda, když to API umí pěkně s těma autoinkrementama. Určitě se v některých databázích a knihovnách dá doptat na následující hodnotu toho generátoru autoinkrementu, takže proč si ji tam nevložit spolu s novým řádkem autoinkrement ji snad nepřepíše, když je součástí insertu, ne?
Co jsem zahlédl někde nahoře obšívání se co když budou dvě hodnoty generované… a je k takovým „věcem“ vůbec důvod? Generovat dvě hodnoty do jednoho DB řádku mi příjde jako absolutní redundantní neužitečný nesmysl (nemluvím o calculated fields či defaults)
Mapování vložených dat na skutečně uložená jde udělat docela dobře se šikovným API a jinak defaults jsou užitečné akorát na vkládání prázdného řetězce či nuly podle typu sloupce, max ještě ten timestamp… Správný program si ale poctivě vloží stejně celou řádku jak potřebuje a na zbytek jsou DB triggery
protoze skrz to mnozstvi stromu lide nevidi les bych to zase jednou rad pripomnel.
Vsimnete si prosim, kolik knih, textu, clanku, disertacnich praci, hodin vyuky, serialiu a buhvi co jeste se nahromadilo kolem toho tema SQL. Triger tak ci onak, v jedne databazi to jde, v jine to nejde, tohle se v te databazi obchazi takhle, neco jineho se obchazi zase jinak, nejaky postup by zabral stovky milisekund, v jine databazi to jde rychle, SQL je primitivni, ze by to mela umet cvicena opice ale co chvili je treba volat specialistu, ktery problem analyzou provadecich planu zkusi resit. Z dalky pozoruji, ze se stale vetsi komplexitou pozadovanych reseni se sql-databaze stale vice hlti.
Rikam z povzdali, protoze jsem uz 25 let usetren teto nesmyslne problematiky. Ukladam i nadale jako prvni den data do ctree-databaze a za tu dobu se neztratil jeste ani byte. (a to se v servrovnach u tech servru ktere spravuji take uklizi a uklizecka by mela tedy minimalne jednou za mesic vytahnout ten kabel :-)) A to skoleni pro praci s takovou databazi trva tak 10 minut. Jsem rad, ze jsou na svete jeste zakaznici, kterym je to totalne fuk, jak se uchovavaji data, jde jim o reseni problemu. Pravda, nejsou to banky, velke korporace, centraly politickych stran ani nemocnice.
Kdokoliv, kdo dělá 25 let s jedním systémem je ušetřen řady problémů.
Většina, neříkám, že všechny problémy vznikají z neuchopení konkrétního sw vývojářem – a je jedno, jestli je důvodem nezkušenost nebo omyl. Pokud pracujete 25 let s jedním systémem, tak nezkušenost nehrozí a že byste očekával od systému něco jiného asi také nehrozí.
Ok. Takže se dohodnem – vybereme jednu db a všichni pojedou na ní?
všechny ostatní? když už to umí MSSQL …
begin transaction
create table dbo.omg(id int not null)
select *
from information_schema.tables
where table_name = ‚omg‘
and table_schema = ‚dbo‘
– vyselecti jeden radek
rollback transaction
select *
from information_schema.tables
where table_name = ‚omg‘
and table_schema = ‚dbo‘
– vyselecti nula radku
např. postgresql.
postgres=# begin;
BEGIN
Time: 27,588 ms
postgres=# create table xx(a integer);
CREATE TABLE
Time: 200,168 ms
postgres=# insert into xx values(10);
INSERT 0 1
Time: 35,007 ms
postgres=# rollback;
ROLLBACK
Time: 0,682 ms
postgres=# select * from xx;
ERROR: relation „xx“ does not exist
LINE 1: select * from xx;
^
postgres=# create table xx(a integer);
CREATE TABLE
Time: 1,445 ms
postgres=# \d xx
Table „public.xx“
Column | Type | Modifiers
--------±--------±----------
a | integer |
postgres=# begin;
BEGIN
Time: 0,250 ms
postgres=# alter table xx add column b integer;
ALTER TABLE
Time: 0,537 ms
postgres=# insert into xx values(10,20);
INSERT 0 1
Time: 0,474 ms
postgres=# select * from xx;
a | b
----±---
10 | 20
(1 row)
Time: 0,380 ms
postgres=# rollback;
ROLLBACK
Time: 0,475 ms
postgres=# select * from xx;
a
(0 rows)
Time: 1,129 ms
postgres=# \d xx
Table „public.xx“
Column | Type | Modifiers
--------±--------±----------
a | integer |
Cau tak pridam taky svoji trochu do mlyna. Velmi jsem se tesil na 5.1 ktera prinesla konecne databazove joby, ktere se jmenuji eventy. Do te doby to resim krkolomne pres crona. Jakmile ji pustili tak jsme migrovali a ja to radostne prepsal do eventu. Eventy fungovaly perfektne, maji ale pro me fatalni problem. Obcas se komplet vypnou a to bez jakehokoli upozorneni, erroru at uz v logu systemu nebo databaze proste najednou se prestanou poustet. Me fungovaly v pohode 14 dni, patnacty den se vyply a ja si toho dalsi 3 dny nevsiml coz nam zpusobilo paseku. Pomuze pouze restart celeho mysql pak nabehnou a mysql se tvari jako by nic. Opet to bezi nejakou nahodnou dobu a po delsi dobe zase vypadnou. Jelikoz to je zatim neosetrene velmi nedoporucuji je pouzivat, pokud mate v jobech nejake dulezite operace!!!!
Operátor IN nie je unlimited a to je problém – asi siahaš za jeho možnosti.
Manuál píše: „The number of values in the IN list is only limited by the max_allowed_packet value.“ Takže zmeň hodnotu max_allowed_packet_value alebo lepšie riešenie je prehnať výsledok cez svoju funkciu, ktorá mnoho idečiek rozdelí do viacero IN() skupín pomocou operátora OR ;-).
Nejvíc jsem v praxi asi narazil kvůli (o komentář výše zmíněnému) nepoužívání indexů uvnitř sub selectů. Tedy třeba
SELECT * FROM (SELECT * FROM customers) ORDER BY name
nepoužije index nad customers.name. Vtipné je, že pokud bych totéž zapsal pomocí view (tj. vznitřní select bych uložil jako view), index by se použil.
Řada odlišností se týká MyISAM a InnoDB tabulek. Kromě zmíněné absence full text indexů v InnoDB (ale ony reálně zas tak užitečné stejně nejsou) se jinak chová AUTO_INCREMENT. InnoDB nezaručuje, že nepřidělí již dříve použitý a smazaný index, protože si prostě hodnotu auto incrementu nepamatuje. Stejně tak nelze v InnoDB použít autoincrement nad klíčem tvořeným více sloupci.
Mám také pocit, že transakce se nesnesou s uzamykáním tabulek, takže i příkaz LOCK automaticky commitne transakci. Ale možná je to složitější a jen kecám.
Na druhou stranu, MySQL přišla s několika veleúspěšnými rozšířeními, které ostatní databáze mohou jen závidět (tedy byl bych raději, kdyby se zmohly i na víc než jen závidění ;) takže odsuzovat ji jako neschopný kus software není fér.
V INNO DB nelze kromě fulltextových indexů používat ani spatial indexy :( Sice to zní pěkně, že MySQL umí kde co, ale prakticky je dost nepoužitelné, protože si musíte vybrat, kterou „půlku“ věcí chcete používat.
Jinak je fakt, že některé věci se mi na MySQL líbí a kdyby opravili/dodělali ty zmíněné nedostatky, tak by to byla i celkem fajn DB. Ale to bude trvat ještě dlouho, pokud se tak vůbec stane.
Další věc je jakási licenční nejistota. Myslím, že většina lidí ani neví, kdy lze použít MySQL zdarma a kdy nikoli. Myslím, že to v poslední době také nějak změnilo.
InnoDB si autoincrement udrzuje v pameti takze pokud nespadne mysql tak je to jeste dobre.. V pripade padu, si InnoDB ziska pri startu posledni id cca dotazem
SELECT MAX(ID) FROm tables FOR UPDATE…
Pokud tedy posledni radek smazu, restartnu db, novy radek bude mit autoincrement onoho smazaneho.
Pokud se nepletu autoincrement muzes mit nad vice primarykey, jen musi byt prvni.
S tím AUTO_INCREMENT
to je trochu složitější. Zvýší se např. i při rollbacku transakce, kde byl zvýšen (což by možná neměl), ale při restartu ne (jak popisuje Petr Bíža).
LOCK
transakci skutečně commitne.
Netvrdim ze pri restartu db se zvysi autoincrement, to v zadnem pripade. Pri restartu se autoincrement zjisti znovu a to pri prvnim INSERT INTO (at jsem presny) a zde prave je zakopany pes.
Pokud napriklad vytvorim prazdnou tabulku a v definici mam auto_increment = 10 a restartnu DB tak po restarnu a vlozeni prvniho radku bude auto_increment = 1.
Při rollbacku by se rozhodně snižovat neměl. AUTO_INCREMENT by měl stát mimo transakci. Jinak by mohl nastat problém v situaci, kdy si (někde mimo databázi, třeba v cache) uložím id vloženého záznamu a provedu rollback, ale „nezapomenu“ hodnotu id. Pak získám při dalším insertu opět stejné id. A jsem v situaci, kdy mám dvě stejné hodnoty, které by měly ale odpovídat různým záznamům v databázi.
Ukládat si do cache řádek, který není v databázi, je nesmysl.
ROLLBACK by měl databázi vrátit do stavu před zahájením transakce. Někdy to samozřejmě nejde (např. když dvě transakce vloží dva záznamy a dřívější si to potom rozmyslí, tak v záznamech vznikne díra), čistě akademicky by se to ale takhle chovat mělo. Proč to tak není? Byla by s tím práce navíc a nikoho to vlastně netrápí.
Nemyslím si, že to je nesmysl, cache byl jen příklad. Zcela reálně se může stát, že v průběhu transakce nastane chyba a dojde k rollbacku a nová IDčka zůstanou „viset někde v aplikaci“ v části, která není (a ani snadno nemůže být) ošetřena transakčně (např. právě ta souborová cache). Nechme stranou, že zápis do těchto vrstev je možné provést až po skončení transakce…
Podstatné u rollbacku vidím spíš, že musí dojít k zachování integrity dat. Data se opravdu vrátí do stavu před začátkem transakce. Auto increment ale možná spadá i do oblasti metadat – může být i součástí CREATE TABLE statementu.
Nevim jak je to u MySQL ale u Oracle sekvence jako jedina neni uzavrena v transakci. A pri rollbacku se jeji hodnota nevraci. Existuje i NOCACHE verze, ktera se chova a tak jak navrhujete, ta ma ale jeden podstatny problem. sekvence se pak stava bodem synchronizace a DB nemuze pridelit dalsi ID dokud prvni transakce neskonci. Je zajimave kolik lidi rozciluje fakt, ze v IDckach mohou byt „diry“ a zpusoby jak to obejit jsou jeste zajimavejsi. Uz jsem videl system kde IDcka nepridelovala sekvence, ale aplikace. Protoze ale byly aplikacni servery dva, musely si cisla sekvence synchronizovat pres RMI. Kdyby jeden server prestal fungovat tak by nefungoval ani ten druhej.
Díky za upozornění. Překlep a ještě jeden nesmysl v perexu jsem opravil.
Na svou obhajobu uvádím, že jsem tento perex nepsal (původní verze). Upravil ho asi někdo v redakci a nikdo už to nezkontroloval.
jeste jsem si vzpomnel, mam dotaz, kde je rekneme pet subselectu, ktere ruzne urpavuji podminky
temp table v celem dotazu lze ale pouzit jen jednou
temp tabulku si vytvorim na zacatku requestu, kde se pripravi prepocitana user data – behem zpracovani skriptu se pak s touto tabulkou pracuje mnohokrat – overuji se ACL k objektum atd atd …
prijde mi to jako celkem neprijemna vlastnost, ale netusim, ak jsou na tom jine databaze a uz vubec, jak to obejit
a jeste jedna – pouziti GROUP BY v subselectu – naivne jsem si myslel, ze databazi usetrim cas, kdyz ji odfiltruji duplicity pres GROUP BY id, nicmene rychlost je casto v radu jinde s/bez teto klauzule
databaze radeji prijme 5000 radku a sama si je prechrousta v ramci podminky, nez aby dostala 50 radku a tyto pak porovnavala
predpokladam, ze todle vychazi spise z me neznalosti logiky procesu do takove hloubky, ale tak …
1. Trošku mě vadí, že MySQL neumí převést „český“ text na „cesky“ – někdy se to hodí, např. pro tvorbu URL adres, a nezdá se mi, že by to byl tak neřešitelný problém (když už má pro každou kolaci vlastní soubor, kde má vše o daném jazyku řečené, tak proč ne i transliteraci do základní latinky).
2. Líbila by se mi funkce vracející, kolikrát se v daném textovém sloupci vyskytuje jiný text zadaný jako parametr (ne nutně jako celé slovo). Neznáte nějakou? Rád bych se s ní seznámil a časem třeba i něco víc. :-)
3. MySQL mi (ve čtyřkové verzi) nedovolila použít UNION ze dvou dotazů používajících v podmínce MATCH…AGAINST nad dvěma sloupci s rozdílnými COLLATION – (Illegal mix of collations..) – i v případě, že jsem podle nich nepotřeboval řadit.
4. Máte nějaké zprávy o úložišti FALCON?
pevne doufam, ze tohle je moje blbost, pac jsem si s tim ted uzil pul dne moru …
vecer jsem (blby napad :) upravoval konfiguraci mysql – upravoval velikosti innodb_* … po startu byla databaze poskozena (prestoze jsem velikosti vsech logu apod. zvetsil) … budiz, predtim jsem provedl zalohu
naimportoval jsem si zalohu, parada, vse bezi – ma blbost, ze jsem nekouknul aspon namatkou na nejakou tabulku
dnes jsem prisel na to, ze vsechny tabulky mam misto innodb myisam a cizi klice v tahu – KURNIK!
mysqldump -p -u root -R databaze – jsem mel za to, ze proste dumpne databazi + procedury
posypu si na hlavu, jestli je to moje blbost, ale …