BEGIN TRANSACTION …

(by: Jasmin Azemović)

Random data and SQL Server (re-write)

with 2 comments

Prije par sedmica imao sam potrebu da iz baze podataka izdvojim određeni broj zapisa i to slučajnim izborom. E sada tu su se pojavili razni problemi, SQL jezik nema komandu koja bi “zagrabila” TOP n zapisa, malo promiješala i izbacila potpuno “RANDOM“.

Npr. Ako želim da iz baze AdventureWorks (tabela Person.Contact) uzmem prvih 5 zapisa kucam komandu koja izgleda ovako:

SELECT TOP 5 ContactID, FirstName
FROM Person.Contact

Retultat izvršenja će biti poredan prema PK u ovom slučaju ContactID (jer nisam drugačije definisao sa ORDER BY klauzulom).

ContactID     FirstName
———–        ————-
1                    Gustavo
2                    Catherine
3                    Kim
4                    Humberto
5                    Pilar

(5 row(s) affected)

Koliko god se mi trudili da sa ORDER BY korigujemo goren navedeni upit i promjenimo redosljed sortiranja…nemamo baš puno opcija, ako želimo RANDOM listu.

Pokušao sam i sa TABLESAMPLE.

SELECT ContactID, LastName
FROM Person.Contact
TABLESAMPLE (10 PERCENT)

Međutim, nije baš random. BOL takođe kaže da ovo nije najbolje rješenje ako želimo slučajni izbor podataka. Šta sad?

Rješenje je generalno vrlo jednostavno, mada ima svojih prednosti i mana. Sigurno svi znamo za funkciju NEWID(). Ista generiše uniqueidentifier vrijednost koja je definitvno jedinstvena. To je svima nama dobro poznati 16 bitni GUID. Ako NEWID() svaki put generiše drugačiju GUID, zašto isti ne bi mogli primjenili u ORDER BY klauzili? Vratimo se na prvi upit:

SELECT TOP 5 ContactID, FirstName
FROM Person.Contact
ORDER BY NEWID()

Nakon izvršenja, redosljed sortiranja će bit drugačiji nego u listingu 1..pritisnimo ponovo F5, pa opet F5, pa opet F5….rezultat izvršenja će svaki put vratiti drugih 5 zapisa. Ovo je definitno riješilo moj problem. Možda će ilustrativnije biti ako se TOP 5 promjeni na TOP 1. Sada će te nakon F5 svaki put dobiti drugi zapis (kao i u prvom slučaju), ali se bolji primjeiti razlika.

Koji su side effects ove metode? Ima jedna mana (koliko sam ja mogao promjetiti..nisam puno ulazio u problematiku). Naime, na jako velikim tabalema  (par stotina hiljada zapisa ili nekoliko miliona) NEWID() treba da se generiše za svaki od tih zapisa i pa tek onda uradi ORDER BY. To je procedura koja može uzeti JAKO puno vremena. Tabela Person. Contact ima malo više od 19 000 zapisa tako da problem sa performansama nije baš uočljiv, ali ako pogledamo execution plan izvršenja našeg upita gdje se generiše NEWGUID() i po istom sortira (nije indekisran) onda stvar postaje malo jasnija.

Kako god,  meni je ovo riješilo problem, vjerujem da ako neko od Vas bude imao slične zahtjeve..NEWID() je nešto što definitivno trebate uzeti u razmatranje.

END TRANSACTION
Advertisements

Written by Jasmin Azemović

08/08/2011 at 22:28

Posted in Database, SQL, SQL Server, TSQL

2 Responses

Subscribe to comments with RSS.

  1. Pozdrav Jasmine,

    Hvala na ovom korisnom riješenju.

    Adnan Džaferović

    15/08/2011 at 13:35


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: