Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

July 20, 2012 / by Zsolt Soczó

Ártatlan kis 1 lapos lekérdezések

Csalóka az adatbázis. Sokan félreértik, mire való, és a 90-es évek stílusában minden vackot rábíznak, ettől persze megfekszik szegény. A félreértés onnan ered, hogy az MS akkor azt mondta, spben kell megírni az üzleti logikát (mivel a VB használhatatlan volt, a C++ meg a legtöbb ember kezében csak bug gyártásra jó). A Delphi ezért élte a fénykorát.
Na szóval, amikor szegény dbre sok üzleti logikát bíznak, akkor mivel őbenne nem lehet a hagyományos módon cache-elni mint egy appszerveren, így az összes piszlicsáré, a büdös életben nem változik de legyen a dbben mert az jó adatot is táblákból kell kiolvasni. Pl. az enumok értékét, amit azért nem szoktunk megváltoztatni a dbben, mert ehhez úgyis a programozott enum értékeket is át kéne írni, ráadásul a kettőt egyidőben szinkronban.
Így aztán a tízmilliós vasú SQL Server olyan dolgokon dolgozik, ami nem az ő feladata. 1 lapolvasás nem a világ, és különben is memóriában vannak a pici táblák, nem jelent ez nagy terhelést.
Valódi cacheből, appszerveren felolvasni egy pl. egy stringet pár nanonsecundum.

Nézzük meg ezt SQL Serveren belülről:

declare @i int = 1000000, @a varchar(200)

while (@i > 0)
begin
	select @a = s.Value from Setting s where s.Name = 'TestSetting1';
	set @i-=1;
end

A Setting tábla két soros, és rendes voltam, raktam clustered indexet a Name oszlopra. 15mp-ig tart a ciklus, a select nélkül kevesebb, mint 1 mp (kb. 800 millisec).
Azaz a select általi kiolvasás kb. 15us, míg ugyanez az appszerveren nanosec nagyságrendű. Nem mindegy.
Ha már ennyire szerelmesek vagyunk az adatbázisba, akkor még azt meg lehet tenni, hogy paraméterként adjuk át neki ezeket a well-known beállításokat.

Pl.

create proc Teszt1
as
declare @a varchar(200)
select @a = s.Value from Setting s where s.Name = 'TestSetting1';
go

create proc Teszt2
@par varchar(200)
as
declare @a varchar(200) = @par
go

declare @i int = 1000000, @a varchar(200)
while (@i > 0)
begin
	exec Teszt1;
	set @i-=1;
end
go

declare @i int = 1000000, @a varchar(200)
select @a = s.Value from Setting s where s.Name = 'TestSetting1';
while (@i > 0)
begin
	exec Teszt2 @a;
	set @i-=1;
end

28 vs 12 mp, látszólag nem nagy deal, de egy terhelt szervernél minden gramm számít.

Ps. sok cégnél láttam ilyeneket, senki ne vegye magára.

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

12 COMMENTS

  • kkető July 20, 2012

    Igazad van. Mindazonáltal nekem gyakori tapasztalásom az, hogy hiába teszi le az ügyfél a nagyesküt, hogy teszem azt az x név lista, csak egy sima felsorolás, se mennyiségre, se belsejében (a nevek) sose változnak (ld. akár enum)…. és pár hét… hipp, hopp… dehogynem… , sőt… kiderül, hogy még az egyes elemeknek property-jei is lesznek…., azaz enum-ból mennek át valódi entitásba
    magyarul vagy a programba lehet nyúlkálni, vagy más tárolóban (ld. registry, app.config, szabadon választott)
    Szóval, nehéz meghatározni, hol van a beégetett adatkör és a db-ben tárolt adatkör közötti homályos határ :)

  • firestrm July 20, 2012

    Épp most próbáljuk megértetni egy nem csak fiatalokból álló csapattal, hogy felejtsék már el a stored procedure-t az O/R mapperek korában! Egy korábbi rendszerüket kell továbbfejleszteni, és minden SP-ben van. Több oldalas SQL-ek, saját bevallásuk szerint is azzal megy el a legtöbb idejük, hogy ezeket karban tartsák, átírják, megírják, de nem hajlandóak lemondani róla, mert, mert, mert… csak. Szomorú, hogy ennek a szakmának is a régi hagyományokkal kell küzdenie lépten nyomon, pedig szinte kétévente gondolkodásmódot kellene váltani (kis túlzással), nem a hypeok miatt, hanem mert egyszerűen ilyen tempóban fejlődik.
    (Arról már nem is szívesen beszélek, hogy minden táblanév és mező úgy meg van rövidítve, hogy szinte kitalálhatatlan, mire is való.)

  • rada July 20, 2012

    Szép-szép az orm, de van amikor az sp célravezetőbb. Nem mindig szükséges/célszerű utaztani az adatokat a hálózaton, még ha az orm rendszer szuper sql-t készít akkor sem.

    Ha pedig az 1-2 oldalnyi sql kódot lecseréljük 1-2 oldalnyi orm-es kódra nem hiszem, hogy olyan sokat javulna a helyzet.

    Azt meg hogy 1/2-1-2 évente teljes koncepcióváltás történik, és újra kell tanulni egy csomó mindent, inkább nem kommentálom. Főleg ha egy nagyobb projekt tervezett fejlesztési ideje 2-3 év, és a szoftvernek alaphangon működnie kellene 10-15 évig.

    Fejlesztés esetén talán a legnehezebb, abban határt szabni a vágyainknak, hogy a BL-ből mennyit valósítsunk meg az általunk preferált (hypeolt), és mennyit a ténylegesen optimális helyén (SQL szerver, App szerver, kliens, stb.).

  • hron84 July 21, 2012

    “15mp-ig tart a ciklus, a select nélkül kevesebb, mint 1 mp (kb. 800 millisec).
    Azaz a select általi kiolvasás kb. 15us,”

    Eliras szaga van a dolognak. 15mp != 15 us

  • hron84 July 21, 2012

    @kkető azert ennek mar specko atiras szaga van. Ha valahol valaki azt mondta, hogy ez enum lesz, akkor az igy kerul be a speckoba. Ha elfogadtak a speckot, akkor ott mar nem lehet valtoztatni. Jobb helyeken.

    Egyebkent SP temaban (igaz PostgreSQL) ajanlom meg egy kollega cikket: http://iwillworkforfood.blogspot.hu/2012/07/ovirt-or-ovirt.html szoval azert a “felejtsuk mar el az SP-t” sem jo hozzaallas. Mindennek megvan a maga helye. Van ahol az ORM overhead, van ahol az SP overhead. De sose mondd azt, hogy “felejtsuk el”. Mert az emberek konnyen felejtenek.

  • hron84 July 21, 2012

    @rada meglevo sw-t senki nem fog evente-ketevente ujrairni, de otevente erdemes atnezni az alapokat, mert – foleg, ha frissitik kozben az sw mogotti adatbazismotort, webszervert, egyebeket – lehet, hogy pont az uj modszerekkel lehet hatekonyabba/gyorsabba tenni a szoftver mukodeset. Nem mondom, hogy otevente ujra kell irni, de otevente erdemes atnezni az alapokat.

  • hron84 July 21, 2012

    Na, nem irok tobb kommentet, ez csak egy javitas lesz.

    @kketö ertelemszeruen nem enumot akartam mondai, hanem azt, hogy ha valami adat a specko szerint valtoztathatatlan, akkor az igy kerul be a rendszerbe, ha speckovaltas van, az meg nem ot forint szokott lenni.

  • Soczó Zsolt July 22, 2012

    hron84:
    15 mikrosec, mert 1 millió iterációs tartott 15 másodpercig.

    A többieknek egy külön cikkben válaszolok.

  • rgeorge July 23, 2012

    Nem témába vág, csak a példa kapcsán kell megkérdeznem: a táblanevek Nálad nem többes számúak? “Setting” helyett nem jobb a “Settings”? Az MS ajánlás is a többes szám, nem?

  • Soczó Zsolt July 23, 2012

    Én egyesszámú neveket használok, mivel a Setting tábla Setting reláció neve, kb. mint egy típusnév .NET-ben.

    De tele van az internet pro és kontra érvekkel is, egyik tábor se tudja meggyőzni a másikat (régebben én is többesszámú neveket használtam…).

    Ms ajánlást erről még nem olvastam, érdekelne egy referencia, megnézném.

  • hron84 July 25, 2012

    Railsnel azert kell tobbes szamu tablanevekkel dolgozni, mert az AR-nek ez a defaultja. A User model a users tablaban lakik. A Matrix modell meg termeszetesen a matrices tablaban, ugyanis – meglepo modon – felhasznaltak az i18n modul pluralizacios kepesseget, igy tud valtani – elvben. Egy Mouse -> Mice valtas azert lehet durva kovetelmeny lenne.

  • hron84 July 25, 2012

    Hogy ertheto legyen: Rails-nel sem kotelezo betartani. Lehet custom tablaneved, akar koze sem lehet a modelledhez. Hanem, egy normalis modell kodja ennyibol all:

    class User < ActiveRecord::Base
    end

    es ez egy teljes mertekben hasznalhato modell, a db megszoritasok alapjan olvasott validaciokkal. Eleg sokmindent fel is ismer. Es minden egyenieskedes plusz egy sor ebbe a letisztult kodba.