Cactus

K stands for Kwality

12 October 2007 (ELTE programming) (6 comments)

Meg nem nevezett (mert egyébként semmi bajom vele) EAF4 gyakorlatvezető a következő példakódot prezentálta arra, hogy hogyan egyszerű új elemnek elsődleges kulcsként szolgáló azonosítószámot generálni, az amúgy SQL adatbázisra épülő programban:

int create_index (QSqlTable table)
{
  for (int id = 0; ; ++id)
  {
    bool found = false;
    for (int i = 0; i < table.rowsNum() && !found; ++i)
    {
      if (id == table.getRow(i)["id"])
        found = true;
    }

    if (!found)
      return id;
  }
}

Kész bazmeg, ilyen nincs, kifekvés meghalás megkészülés. Kérdezem tőle, tudja-e, hogy ezt meg lehet csinálni jobban (maximumkeresés) és jól (rábízni az egészet az adatbázismotorra)? Erre azt mondja, hogy igen, lehet ezt az adatbázisban is megoldani: felveszünk egy egysoros, egyoszlopos táblát, amiben a legutóbb kiosztott azonosító van, és ezt mindig növeljük egyel, amikor valamelyik táblába új elemet rakunk be.

Erre meg már tényleg nem tudtam mit lépni. Mit lépni, szaladni ki a világból!


« Jönnek a letölthető Wii demók? 
All posts
 Egy jó doboz bármit elad »


cooldavee 2007-10-14 17:41:51

Mint végzett programtervező matematikus, én szégyellem magam, nekem kellemetlen.

Csak a műszakisok meg nem tudják, hogy az ELTE-n ilyen idiótákat is megbíznak gyakorlatvezetéssel... :-|

Encsé 2007-10-14 23:10:40

Így igaz, én is ott vezettem!

Lőry 2007-10-15 16:54:15

Eddig ahány adatbázismotort láttam, mind másként viszonyult az egyedi azonosítókhoz. A sorozattábla tehát szvsz nem olyan hülyeség, mint elsőre hangzik. Quick'n'dirty megoldásként elmegy, ha crossplatform SQL-t használva kell azonosítókat kiosztani, és nem számít a insertek párhuzamosíthatóságának elvesztése .

Én is csináltam ilyet egyszer, amikor egy kódnak hirtelen egyszerre kellett volna MySQL meg Oracle felett futnia. Az adatbázis szinte soha sem változott, tehát a kutya se szarta le, milyen hatékonysággal lehet párhuzamosítani az új adatok felvételét.

Aztán egy pár hónappal később egy üres délután motorspecifikus megoldásokra cseréltem a kódot. (A MySQL esetében, megjegyzem, ezután is megmaradt a sorszámtábla: így az ízléstelen szemantikájú auto_incrementek megmaradtak ebben az egy táblában, és nem kellett telefikázni velük az egész sémát.) A hatékonyságbeli különbség nem volt mérhető, de a komplexitás egy picit megnőtt. Így utólag azt kell mondanom, szerintem úgy kellett volna hagynom, ahogy eredetileg összecsaptam: az a kód jobb volt.

cactus 2007-10-15 19:45:21

Szerintem ha tenyleg olyat csinalsz, hogy amig egyvalaki irni akar barmely tablaba, addig write lockolod az egesz dbt, akkor eleve barmilyen adatbazismotort hasznalni overkill.

Vagy az ID-tabla tobb soros lenne, es lenne egy KTabla is hozza? Es akkor annak a megf sorat lockolod + persze megintcsak a teljes celtablat? Ez is eleg ganynak hangzik.

A konkret SQL semat meg generaljad valami intencionalisabb inputbol, hat pont neked magyarazzam ezt?!

Lőry 2007-10-16 15:21:35

Három sor, három válasz:

1. Ismétlem, az adatbázis szinte sosem változott. Ellenben folyamatosan és hatékonyan le kellett tudni kérdezni. Az adatbázismotor nem csak azért jó, mert könnyen lehet benne adatokat tárolni-változtatni-visszakérdezni. Az adott alkalmazásban talán a legfontosabb előnye a megbízhatóság, auditálhatóság és katasztrófahelyzet esetén könnyű visszaállíthatóság volt. Ráadásul sosem steril vákumban fejleszti az ember az alkalmazást, hanem az adott intézet/cég szokásaihoz-munkakörnyezetéhez-szabályaihoz illeszkedve. A szóban forgó intézetben volt egy remek adatbázis-backend szolgáltatás, és a helyi policy része volt, hogy az éles adatokat abban tároljuk, nem random szerteszét szórt fájlokban.

Vegyük észre egyébként, hogy a szekvenciatáblás megoldásban nincs szó teljeskörű write-lockról, csak az _új_ adatok felvételét szekvencializálja a megoldás, és azt is csak akkor, ha ténylegesen minden INSERT előtt egy UPDATE jön a sequence táblára. (A konkrét rendszerben egyéb technikai sajátosságok miatt erre nem volt szükség, így elvileg párhuzamosan is lehetett volna (helyesen) adatokat felvinni. Nem mintha a gyakorlatban ez egy picit is számított volna.)

2. Igen, minden adattáblához külön sorozat tartozott, ergo külön sor a sorozattáblában. A business logic legalsó rétegeihez az Active Row mintát követtük, és hasznos volt, hogy különösebb erőfeszítés és motorspecifikus varázslások nélkül előre meg tudtuk mondani, hogy mi lesz a soron következő sor azonosítója.

3. Overkill, anyone? A konkrét sémákat _természetesen_ egy magas szintű leírásból generáltuk. _Természetesen_ kézzel. Persze, lehetett volna hónapokig szenvedni egy cross-platform sémadefiníciós modul megírásán. Ehelyett mi buta módon összesen kb. egy délután alatt elkészítettünk és leteszteltünk két tökéletesen működő SQL sémadefiníciós parancssorozatot, majd a következő hónapokat inkább a konkrét feladat megoldásával töltöttük, mert ezért fizettek, és nem azért, hogy egy elefántcsont-toronyban verjük a faszunkat.

Nincs abszolút értelemben jó vagy rossz program. A konkrét feladat, a költségek, határidők, a helyi szokások, belső politikai döntések erősen befolyásolják azt, hogy az adott helyzetben mi az optimális megoldás. Aláírom, a legelső általad idézett megoldás nehezen védhető. A sorozat-táblás ötlet viszont adott esetben akár relatíve a legjobb megoldás lehet, mint ahogy sokminden más is.

cactus 2007-10-17 21:41:22

Az elejet nem ertem, hiszen a sok lekerdezest jottanyit sem lassitana, ha a beszurasokkor a motor altal menedzselt unikus ID-ket hasznalnank.

Ami meg szerintem a lenyeg, hogy lehet, hogy ket eve progkör gyakorlaton sem volt teljesen igazam, amikor azzal jottem, hogy jobb helyeken mar ot eve is szivlapattal vertek agyon azt, aki a FONT HTML tag-et hasznalta, de

ezt a kocerajt jobb hijan ugy hivjak (meg?) hogy egyetem, es mint ilyen, szerintem igenis ne ilyen megoldasokat mutassunk a hallgatosagnak, vagy legalabbis ne elsore.