Gå til innhold

Forskjellige måter å opprette primærnøkler?


Anbefalte innlegg

Jeg har laget tabellen:

 

CREATE TABLE plattform (

id int NOT NULL AUTO_INCREMENT PRIMARY KEY,

navn varchar(255),

utgivelsesaar int);

 

Kunne jeg like godt gjort det slik:

 

CREATE TABLE plattform (

id int NOT NULL AUTO_INCREMENT,

navn varchar(255),

utgivelsesaar int);

PRIMARY KEY(id)

 

?

 

Eller er det noen regler for når PRIMARY KEY skal stå på samme linje, og helt til slutt?

Endret av pengolf
Lenke til kommentar
Videoannonse
Annonse

Akkurat hvor du setter primary key setningen spiller forsvinnende liten rolle, men det som spiller en rolle er at du kjenner til de valgmulighetene du har på primærnøkkelen, samt hva som er standardvalg. Ta for eksempel i MSSQL:

 

create table epostlog (
 meldings_hash binary(16) not null primary key,
 avsender varchar(120),
 mottaker varchar(120),
 emne varchar(120),
 tid datetime2(0)
)

 

Noen vil sikkert si at en primærnøkkel på 16 byte er for stort, men hvis vi ser bort i fra det, er det noen som ser hva det ytelsesmessige problemet med primærnøkkelen er i dette tilfellet?

Lenke til kommentar

... og for postgres så vil en slik deklarasjon være ok, (la oss si at vi skal lage en tabell ordre med referanse til en kunde tabell som er lagd tidligere)

 

CREATE TABLE order (

orderid serial PRIMARY KEY,

id_contactid integer REFERENCES contact

);

 

Det vil bli lagt en primary key constraint på orderid og en foreign key constraint på id_contactid som vil referere til primary key-en i contact tabellen.

 

Kjappt å skrive, lett å lese :)

Lenke til kommentar
Akkurat hvor du setter primary key setningen spiller forsvinnende liten rolle, men det som spiller en rolle er at du kjenner til de valgmulighetene du har på primærnøkkelen, samt hva som er standardvalg. Ta for eksempel i MSSQL:

 

create table epostlog (
 meldings_hash binary(16) not null primary key,
 avsender varchar(120),
 mottaker varchar(120),
 emne varchar(120),
 tid datetime2(0)
)

 

Noen vil sikkert si at en primærnøkkel på 16 byte er for stort, men hvis vi ser bort i fra det, er det noen som ser hva det ytelsesmessige problemet med primærnøkkelen er i dette tilfellet?

 

Hmmm... aner ikke noe om sql server, men det kan vel være at sammenligning av binary datatyper er tregt? Kanskje binary felter blir lagret utenfor resten av tabellen? Med 64bits prosessorer på 64 bits os med 64 bits programmer så vil all sammenligning av data på mer enn 8 byte ta vesentlig lengre tid enn datatyper på mindre enn 8 byte...

 

Så, gjettet jeg riktig på noen av punktene? :p

Lenke til kommentar
Noen vil sikkert si at en primærnøkkel på 16 byte er for stort, men hvis vi ser bort i fra det, er det noen som ser hva det ytelsesmessige problemet med primærnøkkelen er i dette tilfellet?

 

Du tenker vel på at PRIMARY KEY defaulter til CLUSTERED siden det ikke er definert andre UNIQUE constraints som CLUSTERED. Og siden kolonnen sannsynligvis er en hashverdi, fra navnet å dømme, så er jo det ytelsesmessige problemet åpenbart.

 

Må forresten få si at "Tuning og Optimization" kurset jeg er på hos MS er veldig interessant. Kursholder er en "gal" (i positiv forstand) inder som tidligere jobbet i SQL Server utviklingsteamet i Redmond (vel og merke ikke med 2005). Han vet de snodigste ting :)

Lenke til kommentar

Kaffenils har helt rett. SQL Server defaulter til clustered primary key, og det åpenbare problemet er at alle dataene blir liggende fysisk sortert etter primærnøkkelen, som er tilfeldig av natur. SQL Server vil derfor bruke mye tid og ressurser på å sortere dataene, og du vil få, som Kimberly Tripp så fint kaller det, a perfectly fragmented database.

Lenke til kommentar
Vil det da strengt tatt bli en bedre ytelse dersom man bruker en pk_id kolonne som er en auto increment, og heller ha hashen som en index i tabellen? Altså, om du skal bruke denne hashen til søking, vel og merke.

I dette tilfellet, en type loggtabell, ja. Men, du kan også spesifisere at primærnøkkelen skal være nonclustered for å unngå det problemet jeg beskrev. For tabeller som typisk har meget stor andel selects, og dertil lite insert, update og delete, så vil en clustered index være hensiktsmessig, men det fordrer jevnlig defragmentering av databasen. For å slippe dette kan man, som du også nevner, bruke en surrogatnøkkel, en autoinkrementerende verdi.

Lenke til kommentar
Vil det da strengt tatt bli en bedre ytelse dersom man bruker en pk_id kolonne som er en auto increment, og heller ha hashen som en index i tabellen? Altså, om du skal bruke denne hashen til søking, vel og merke.

 

Hvis du fortsatt skal bruke hashen til oppslag som f.eks. select * from epostlog where epost_hash=0x012345... så vil du få degradert ytelse hvis du i tillegg introduserer en pk_id indentity clustered.

 

Grunnen til dette er at SQL Server vil utføre flere logiske reads enn hvis meldings_hash hadde vært pk nonclustered.

Lenke til kommentar

Korrekt. Men, for en typisk loggtabell som har stor grad av innsetting, så vil den totalt sett kunne tjene på dette fremfor å ha epost_hash clustret. De ekstra read du snakker om er forbundet med å hente opp raden etter at den er funnet i indeks, ikke sant?

Lenke til kommentar

Nå begynner det riktignok å bli ganske off topic, men dog... Dette er en problemstilling som vi fort kan komme til å se mer til når LINQ begynner å tas i bruk. LINQ er ganske så fantastisk, men uvettig bruk (les: quick'n dirty kode) kan fort føre til slike problemstillinger. Andre morsomme problemstillinger vi kan se etter hvert kan inkludere at hele recordsettet sendes over nettverket til klienten, for så å behandles der.

Endret av roac
Lenke til kommentar
Roac: LINQ er såvidt jeg kan se veldig likt NHibnernate som er .Net versjonen av Hibernate?

 

Har brukt NHibernate og det er maaaange fallgruver en kan gå i. F.eks. å sette lazy read (eller hva det nå het) off. Plutselig skal store objekttrær leses og 1000vis av SELECT statements genereres. Hadde en skrevet SELECTen selv så kunne en gjort det samme med én enkel SELECT. Er blitt veldig skeprit til ORM-ing :)

Lenke til kommentar

kaffenils: skriv HQL (ligner veldig på SQL, men du ender opp med objekt-trær og du kan spesifisere nøyaktig hva du skal hente ut)

 

f.eks:

 

Contact contact = (Contact)session.createQuery("FROM contact a LEFT JOIN FETCH a.orders b WHERE a.contactid = :contactid")

.setParameter("contactid ", 5)

.uniqueResult();

 

Det er forresten så å si de samme fallgruvene man kan gå i med ORM som med SQL, det er bare at du har litt mer erfaring. F.eks SELECT * FROM contact, order er en heller lite heldig select ;)

Endret av blackbrrd
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...