2013. február 12., kedd

Rekord "karbantartás"

Sziasztok!


Nemrég esett meg velem, hogy egy syslog file 1 napnyi tartalmát importálni kellett MsSqlbe. Létre is jött egy szerény 5.000.000 darab rekordot tartalmzó import nevű tábla, ami ugye tartalmazott kőkemény 1 db oszlopot, ami egy valami-string típusú volt.

Aki még nem játszott sysloggal: Egy hatalmas,hosszú stringben tárolja el az összes adatot, amit megkapott valamilyen szolgáltatástól (pl Ips) Tehát ugyanabban a stringben fogod látni a dátumot, időt, forrás ip, cél ip, stbstb adatokat. Ugye milyen elegáns?

Szóval, gyorsan kiegészítettem egy id mezővel az import táblát, hogy mégis legyen egy clusterelt index is a családban. (Egyszer úgy kipróbálnám milyen jó játék lehet egy sok gigás adatbázist HEAP struktúrával üzemelteteni :)   )

Ezután futtatam egy ideig a scriptem, amit string-cincáló tárolt eljárásnak neveztem csak el.
(Egy ideig = Egy tisztességes adag amerikai kávét simán elkortyolgattam, mire végzett, dehát érthető is)


Ekkor már megvolt a cél táblám, ami tartalmazott mindenféle ID-t, forrás és cél ip címeket, dátumot, és más egyéb okosságokat.

Már kezdett megfogalmazódni bennem az "ez is megvan, még sincs este" szlogen amit egy cimborámtól szoktam volt kölcsönvenni, amikor megkopoktatták a vállamat, hogy ugyanmár, miért van a rekordok majd' felénél többszöröződés? Mint kiderült, a syslog is így kapta már meg az adatokat, noha ez engem nem vígasztalt, mivel a táblám így nem a valóságot tartalmazza...

Tehát most több millió rekordot nyálazzak át, hogy miben van egy, és miből több...

Eddig a prológus.


Mivel az első google találatok szvsz agyonbonyolított subkveris megoldásokkal akartak segíteni, inkább erőt vettem magamon, és nekiálltam gondolkodni.

Hogyan kellene kitörölni?

1.: Számoljuk meg hogy az X db mezők alapján hány egyforma rekord van.
2.: Ezt irassuk ki a táblával
3.: Ha ez a mennyiség több, mint 1, akkor törlés

Ahhoz hogy ez átlátható legyen, ja és nem mellesleg hatékony Execution Plannel működjön a CTE mellett voksoltam.

Íme:

with cte_tobb_azonos_rekord_torlese
as
(
select row_number() over(partition by source_ip,dest_ip,datum order by source_ip) as sorszam,
source_ip,dest_ip,datum
from adatbázis.dbo.táblám
)
delete from cte_tobb_azonos_rekord_torlese
where sorszam>1



Sziasztok!
Jó munkát! :)



2 megjegyzés:

  1. Ügyes megoldás! :)
    Én is szeretem a CTE-ket, és ez +1 okos érv mellettük.

    VálaszTörlés
  2. Köszi :)

    Igen, emlékszem, hogy a query tanfon is sok mindent CTE-vel csináltál :)


    VálaszTörlés