Count és count_big

A count ugye megszámol valamit, de miért van rá két külön funkció? Mi ez a count_big? Másképpen számolnak? Mást számolnak? Nem igazán. Egyetlen különbség a visszatérő értékük, aminek típusa int vagy bigint.

Akkor meg mi szükség van rá? Hát mert boldog ember, aki még nem ütközött problémába olyannal, hogy egy mező intnek lett definiálva, de kifutott a neki szánt helyből.

MSSQL-ben az intnek, mint egész numerikus értéknek négyféle típusa van:

  • tinyint: 0 és 255 között tud értéket tárolni
  • smallint: -32.768 és +32767 közötti értékekkel
  • int: talán a legáltalánosabb, -2 milliárd 147 millió meg egy kicsi és +2 milliárd 147 millió meg egy kicsi között lehet az értéke, szépen kifejezve 232 (hol van ebben az új WP 5-ben a szöveg formázás?)
  • és a bigint: „nagy” számoknak, ami azt jelenti, hogy -9 trilliárd meg a maradék és +9 trilliárd meg a maradék között, szebben kifejezve 264

Ha nem olyan értéket adunk meg a változónak, amit tárolni tud, akkor egy arithmetic overflow hibával jutalmaz minket:

declare @small_int smallint

set @small_int = 32768

A count_big tehát azért fontos, mert a count visszatérési értéke int lesz, vagyis alig tud 2 milliárd fölé menni. Ha már az adatbázis tervezésnél kiderül, hogy egyes táblák ennél több adatot tárolnának, akkor eszünkbe se jusson sima countot használni. Ha joint írunk és gyanús, hogy a táblák adatai alapján talán szűkös lesz a keret, akkor is count_biget használjunk.

Sőt, én azt sem bánom, ha mindenhol count_biget használunk. Ezzel mit veszítünk? Az eredmény bigint lesz, ami 8 byte-on tárolódik, az int 4 byte-jához viszonyítva. Vagyis vesztünk 4 byte-ot. Ha viszont szükség lenne rá, de nem ezt használjuk, akkor hirtelen hiba léphet fel a lekérdezésünkben, és ha azt nem simán SQL-ben használjuk, hanem egy alkalmazásból, akkor mehet a nyomozás.

Természetesen én bátran mondom bárkinek, hogy 4 byte nem a világ, miközben adatbázis tervezésnél minden byte számít. Egy ember életkora nem lehet több, mint 255 év, használjunk bátran tinyintet. Egy ember havi fizetése ritkán több, mint 2 milliárd forint, szerintem használhatunk sima intet (azon most nagyvonalúan lépjünk át, hogy arra talán nem is intet kellene használni, főleg nem több devizás környezetben). Egy általános banki rendszernél, ahol viszont simán lehet cégek vagy állami intézmények között 2 milliárd feletti utalás inkább használjunk bigintet (megint csak: nem intet fogunk, ez csak a hasonlítás miatti példa).

A kétféle felhasználás között viszont van egy nagy különbség: az adatbázis tervezésnél ezek az 1-2-4 byte-ok soronként rakódnak rá. Ha egy sorunk van és bigintet használtunk, ahol int is elég lenne, akkor csak 4 byte-ot pazaroltunk el. De ha már 1000 sorunk van, akkor már 1000*4 vagyis 4000 byte ment veszendőbe, ami majdnem 4 KB.

A count_big viszont csak visszatérési értékében fogja ezt a +4 byte-ot felzabálni az inthez képest. Nem annyiszor, ahány sor van, vagy ahányszor futtatjuk, hanem annyiszor, ahány külön változót definiáltunk neki. Még ha nagyon nagyvonalúan is bánunk a dolgokkal, vagy hosszú a scriptünk, és 10-15-ne-adj-isten-20 változónk van, akkor is csak 10-15-20*4 byte-tal használtunk többet.

Ezért írtam: vizsgáljuk meg a lehetőségét, hogy az int nem lesz elég, és ha úgy látjuk, hogy ez könnyen vagy a közeljövőben bekövetkezhet, akkor használjuk a count_biget.