Avatar billede Syska Mester
17. december 2009 - 14:54 Der er 7 kommentarer

Dele table op pga mange null's

Hej,

Jeg har en table hvor jeg har en masse NULL values ... og tit er felter ikke udfyldt hvis der er en bestemt type.

Jeg har så overvejet at dele det op i 3 tables ... og måske koble noget af de fælles ting sammen i en table.

Der skal så kunne søges i det ... hvis folk kun vælger noget af en type ... jamen, så skal den selvf kun søge i den ene table ... men vælges der flere, så skal der selvf søges i alle 3 ... det regnede jeg med at kunne lave en union på de X tables.

Det skulle gerne ende med bedre performance ... og så bare for at prøve det ... performance skulle komme ved at antal rows bliver minimeret meget i hver table og så at folk for det meste kun søger i en af de tables.

Er det helt hen i skoven ?

tabellen har 100 mill rows lige nu ... fordelt på 350 server ID'er som der kan søges på ... og det bliver til ca. 3-4 tables efter det er delt op ..

Så vi ender på ca. 330.000 rows  ... som bliver fordelt i de 3 tables ... med en fordeling på 10%, 30%, 60%


En anden ting jeg ikke rigtig kan få til at passe ...
Hvis jeg opretter en table med:
bigint, int
så burde hver row fylde 12 bytes ... men hvis jeg smider 10.000 rows i ... ender det med at fylde ca. 24 bytes per row.

Hvad er det jeg har misset her ? eller er det bare sådan :-s, måske en settings eller ?

mvh
Avatar billede teepee Nybegynder
17. december 2009 - 17:27 #1
Hmm, en integer fylder 4 bytes selvom den er tom. Hvilke datatyper bruger du til tekst? Varchar fylder ikke noget, men char gør. Hvis du begynder at opdele data og kun oprette efter behov så tror jeg at en fælles nøgle vil giver dig nogle langsommere outer join udtræk. Du kan evt. ændre fill factor så der ikke reserves plads i blokkene til evt. fremtidige indtastninger. Så fylder det da lidt mindre
Avatar billede Syska Mester
17. december 2009 - 18:21 #2
Netop derfor jeg vil dele op ... da jeg måske kan spare noget. Men det er stadig kun en tanke om en del af min lærings process med SQL :-)

Nu siger du fælles nøgle ... det er heller ikke tiltænkt ... der er stadig en nøgle, da der kommer mange inserts hver dag. Dog er der et index på "server id" og "type" ...

Fill factor er 100 ... så vidt jeg lige ved ... da det er statisk data ... eneste der kan ske at at det hele skal ud ... fordi det enten bliver for gammel ... eller alt information om den server skal slettes.

Outer join vil jeg ikke have nogen af .. da jeg havde tænkt på netop 3 tables ... med nogen redundante data.

Men at det måske kom til at fylde mindre og hurtigere.

Da den laver 3 queries på 3 tables med en UNION ALL, vil de så ikke bliver eksekveret parallelt ?
Avatar billede janus_007 Nybegynder
17. december 2009 - 22:24 #3
Hej buzz

Nu er 100M rækker stort set lig med ingenting at søge, så jeg tror ikke det vil gavne alverden at dele det op. Med mindre du selvfølgelig har nogle dårlige indexes, men du skal vide at hvis dine queries kører på indexseek så gavner det som sagt intet.

Hvis du insisterer... mht. union så vil den kun foretage en parallel execution plan hvis query optimizeren vurderer at det kan betale sig + at du har cpu'er til det :)

Det som du måske kan lave er et partitioneret view og derved kun få udført søgningen i den / de korrekte table(s) afhængig af din partitioneringsnøgle.

Du kan evt. overveje sparse columns: http://technet.microsoft.com/en-us/library/cc280604.aspx , men husk de performer dårligere på nonnulls :(

Husk at fillfactor på 100 giver rigtigt mange pagesplits på indexet, så overvej nøje den fillfactor :)

Hvor bred er din gennemsnitlige rækker i bytes? Husk at 1 page fylder 8kb og der kan laves meget finetuning :)
Avatar billede Syska Mester
17. december 2009 - 23:40 #4
Hej,

Jeg kan ikke lige svare på det hele i den her mail ... skole projekt skal afleveres i morgen ... og vi arbejder stadig på det. men kan komme med lidt info.

Mine rows har en fast størrelse. (i hvert fald i min forståelse)
ca. 26 bytes
ID - bigint - PK
serverid - smallint
type - tinyint
gruppe from id - int (nullable)
gruppe to id - int (nullable)
user from id - int (nullable)
user to id - int (nullable)
ekstra id - int (nullable)
added - date

så hurtig regning giver: 34 bytes ... ( med mindre nullable field ikke fylder hvis de er null )

and still ... når jeg tager pladsen optaget af den table ( Props på min table, og så under Storage, så står der hvad index og data fylder ) ... giver det i snit 54 bytes. Når mine data nu er 100% statiske med mindre når de bliver slettet ... betyder det så at der er meget ledig plads i min table ? For så kan det hele jo flyttes "MEGET" sammen ... ved at have en fillfactor på 100 ... da jeg kun laver inserts i den table ... og sletter jeg noget ... så ryger alt med 1 bestemt server ID ... eller også efter age ... men så er det ud fra min PK som er en Identity, dvs så burde alle rykker ryde ud, i samme som de kom ind.

Næste problem er at jeg joiner fra de ID'er du kan se ... gruppe/user over på 2 andre tables som underholder navn.

Dette er sådan en ... event table. En bruger kan kun være i en gruppe ... f.eks hvis en bruger bliver flyttet fra en gruppe til en anden ... så vil To/From gruppe id'er fra den gamle og nye.
user id vil så være hans id ... og her vil det ene være null.

Håber du kan se ideen med min table.

mvh
Avatar billede janus_007 Nybegynder
19. december 2009 - 12:51 #5
Nu har du ikke fortalt noget om hvor mange rækker din tabel består af, men en SQL Server allokerer tablespace pr. page, dvs. hvis du kun indsætter 1 række så vil der blive nappet 8KB (pagesize) og reserveret 16KB :)

Fillfactor på 100 har ikke så meget med table size at gøre, udover på det clustered index. Husk stadig at en fillfactor på 100 vil give mange pagesplits over tid, så en god reindexing strategy vil være at foretrække :)

Er det pladsen du skal optimere eller performance?

En anden mulighed er også at normalisere tabellen, det kan sikkert give en bedre pladsudnyttelse, men om performance bliver bedre... tjaa... det kan man kun forsøge sig frem til :)
Avatar billede Syska Mester
19. december 2009 - 21:03 #6
Antal rows står faktisk i mit første indlæg :-) Der skrev jeg:
"tabellen har 100 mill rows lige nu" men det tal var ikke helt rigtigt kan jeg se nu ... så ny info kommer her.

Med 110M rows ... og en row size på 34 bytes ... regnet ud fra data typer ... giver det 6 GB ... men jeg får en size på 12 GB ca.

Derfor mine spørgsmål om hvad der præcis sker, når den allokere, da jeg ikke kan få de 2 sizes til at passe ... :-s ?

Mit problem hvis man kan kald det for et problem ... er måske mine joins ud til andre tables ... som du kan se på overstående table skema jeg prøver at skrive der. Kan du se der sker en masse joins for at få deres navne ud ... altså fra ID til Name.
Gruppe table - 2 joins
Player table - 2 joins
Ekstra id - 1 join

Jeg er åbne for andre alternative måder at kunne lave en table struktur der kan overholde mine krav ... men synes ikke jeg kan komme på bedre ideer.

Men en Fill Factor på 100 ... det kan jeg så forstår gælder både Clustered Index og Non-Clus-Index ...

Her løber jeg så lidt ind i en mur kan jeg se ... så jeg uden tvivl vil så mange Page spilts på mine Index's ... da de bruger en form af: Server id, type og tid, så de kommer i den rigtige række følge når der søges ...

Men data er static ... dvs read only hele dagen, pånær når jeg 1 gang dagligt smider en masse data ind ...

Det er Performance jeg vil optimere mod ... der bør være plads nok eller må jeg bare minimere antallet af servere.

Pladsen er mere sådan videns mæssigt, da jeg ikke kan regne mig frem til hvor meget en table kommer til at fylde ... og det er lidt træls ... :-(

Den er normaliseret lidt, da navnet netop kommer fra andre tables. Data der er tilbage nu er bare ID'er på de ting som omhandler det der er sket ... og der er så flere muligheder.

Håber du kan følge min tanke gang ... og hvis der er noget du er i tvivl om ... så sig endelig til.

Btw. så smider jeg ekstra point i, da det er ved at bevæge sig lidt uden for emnet ... men stadig relavant i forhold til oprindelige spørgsmål.
Avatar billede Syska Mester
11. marts 2010 - 09:10 #7
Smid et svar begge.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester