Permalänk

HEX-kod som unique ID i MySql

Hej!

Har funderat lite på vad som är smidigast att använda som unique id i mysql-databaser? Tycker det är lite kasst i MySql där man i princip by default kör med increment int. Har nu funderat på att sköta indexeringen mha en 20 tecken lång hex-sträng, som jag sett att man gör i andra databaser.

Vad borde vara smidigast, rent indexeringsmässigt, att använda för datatyp för detta ändamål, är det VARCHAR (som jag har för mig är någon fuskblandning och långsam), eller finns det någon HEX-datatyp som jag totalt har missat?

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem

Ett numeriskt värde kan ju vara hex om du vill, det beror vad du presenterar det som. 20 tecken långt är ju lite för mycket för ett 64-bitarsvärde iofs, men du kommer ganska nära.

Det känns som om du är ute efter ett hash-värde, vilket följer lite andra regler. Det är dock ingenting som förhindrar att du kombinerar bägge metoderna, och använder ett numeriskt stegande värde som auto-ID samtigt som du indexerar på en hash!

edit: för att svara på din fråga så vill du sannolikt använda en CHAR(20).
PS. VARCHAR är inte fusk. DS

Visa signatur

Kom-pa-TI-bilitet

Permalänk

Jag tänkte mest använda hex-representation för att det blir färre tecken än binärt eller decimalt. 20 tecken är kanske lite att ta i, för det blir väl 16^20 stycken id:s vilket man inte lär komma i närheten av...

Jag kan ju naturligtvis använda en hash också. Det kan man väl dessutom ställa in så att databasmotorn "by default" lägger använder en 32-bitars hash som nyckel?

Hur menar du förresten att man skall kombinera dem? Ha en hash och en auto-inc som tillsammans bildar en nyckel?

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem

Du säger 16 ^ 20

Ifall du istället tar en BIGINT så blir det 2 ^ 64, vilket blir 16 ^ 60 ifall jag räknar rätt nu på sena timmen
Eller bara en vanlig int, 16 ^28 (32-bitar), d.v.s. fortfarande. Är nog inte i många fal en 64-bitars räcker till

Permalänk
Skrivet av Megamannens:

Du säger 16 ^ 20

Ifall du istället tar en BIGINT så blir det 2 ^ 64, vilket blir 16 ^ 60 ifall jag räknar rätt nu på sena timmen
Eller bara en vanlig int, 16 ^28 (32-bitar), d.v.s. fortfarande. Är nog inte i många fal en 64-bitars räcker till

Det är sant, mycket blir det.

Känner du till om det finns någon inbyggd funktion i MySql som skapar en indexerbar hexsträng?

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Permalänk
Medlem
Skrivet av Megamannens:

Du säger 16 ^ 20

Ifall du istället tar en BIGINT så blir det 2 ^ 64, vilket blir 16 ^ 60 ifall jag räknar rätt nu på sena timmen
Eller bara en vanlig int, 16 ^28 (32-bitar), d.v.s. fortfarande. Är nog inte i många fal en 64-bitars räcker till

en "vanlig" int är fyra bytes. Maxvärdet av en byte är 255 eller FF i hexadecimal notation, så maxvärdet på en styck 32-bitars int == FF FF FF FF. en 64-bitars int blir FFFFFFFFFFFFFFFF, eller sexton hexadecimala positioner (16^60 är förresten åt h-vete mycket mer än 2^64..)

Alltså, en 64-bitars int (BIGINT) räcker precis för ett sexton tecken långt hexadecimalt värde. Naturligtvis sparas det inte som en hexadecimal sträng, utan som ett integervärde precis som det angetts. För att presentera ett numerisk värde som en HEX-sträng kan du använda funktionen HEX(), exempelvis SELECT HEX(255); resulterar i "FF".

Anledningen till att ett automatiskt ökande integervärde vanligtvis används som primärnyckel är för att det är effektivt. Man kan garantera att upp till 2^32 (för INTEGER) rader är unika utan att någon overhead för att generera en unik nyckel tillkommer.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Christhebalrog:

Jag tänkte mest använda hex-representation för att det blir färre tecken än binärt eller decimalt. 20 tecken är kanske lite att ta i, för det blir väl 16^20 stycken id:s vilket man inte lär komma i närheten av...

Hexadecimalt är ju bara ett annat sätt att presentera ett numeriskt värde för användaren för att göra det mer lättläst, internt (inne i datorn) så lagras det ju binärt precis som vilken annan data som helst. Så sett till minnesutrymme blir det ingen skillnad om du väljer att presentera ett tal som oktalt, decimalt eller hexadecimalt eller 'whatever', allt lagras ju ändå likadant(binärt) inne i datorn.

Permalänk
Skrivet av Teknocide:

Alltså, en 64-bitars int (BIGINT) räcker precis för ett sexton tecken långt hexadecimalt värde. Naturligtvis sparas det inte som en hexadecimal sträng, utan som ett integervärde precis som det angetts. För att presentera ett numerisk värde som en HEX-sträng kan du använda funktionen HEX(), exempelvis SELECT HEX(255); resulterar i "FF".

Anledningen till att ett automatiskt ökande integervärde vanligtvis används som primärnyckel är för att det är effektivt. Man kan garantera att upp till 2^32 (för INTEGER) rader är unika utan att någon overhead för att generera en unik nyckel tillkommer.

Då är det alltså idé att använda bigint. Indexeringsmässigt så borde detväl vara smidigt att ha integers istället för VARCHAR. Dock så lagras väl även CHAR som ett numeriskt värde, så ur prestandasynpunkt kanske det borde vara hugget som stucket? Om man dessutom kör unsigned så borde man få ytterligare en bit att lagra info på. Fast BIGINT kanske per definition är unsigned?

Skrivet av Didonk:

Kan funktionen UUID() vara vad du söker?

Absolut, skall kolla vidare på denna!! Jag skall nog sluta försöka lösa problem mitt i natten, och leta själv istället. Nu kände jag mig bara extremt lat, förlåt.

Skrivet av Killer-Duck:

Hexadecimalt är ju bara ett annat sätt att presentera ett numeriskt värde för användaren för att göra det mer lättläst, internt (inne i datorn) så lagras det ju binärt precis som vilken annan data som helst. Så sett till minnesutrymme blir det ingen skillnad om du väljer att presentera ett tal som oktalt, decimalt eller hexadecimalt eller 'whatever', allt lagras ju ändå likadant(binärt) inne i datorn.

Jo, det vet jag. Min tanke var att från början köra en indexering på VARCHAR, vilket jag misstänker blir förfärligt ur prestandasynpunkt om man jämför med BIGINT eller CHAR. Jag tror jag blandade ihop hashsummor och id...

Förresten, om jag anger en datatyp som binär, påverkar detta prestandan i indexeringen? T.ex. att overheaddata försvinner osv? Sen så pratade någon om att kombinera id med hash, vad tjänar man på det? Har inte sysslat med hashning tidigare mer än att spara lösenord...

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem

Den verkliga frågan är: räknar du med att din tabell kommer att ha mer än fyramiljardertvåhundranittiofyramiljonerniohundrasextiosjutusentvåhundranittiosex rader? Om svaret är ja behöver du köra BIGINT, annars inte.
Indexering på [VAR]CHARS (du vill troligtvis använda CHAR till en sträng med fast längd) ska inte bli direkt långsammare, jag gissar att databasen bygger upp någon sorts hashmap i bakgrunden. Däremot tar det ju extra utrymme och innebär overhead när hash-värdet för en rad ska räknas ut i samband med INSERT.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Teknocide:

Den verkliga frågan är: räknar du med att din tabell kommer att ha mer än fyramiljardertvåhundranittiofyramiljonerniohundrasextiosjutusentvåhundranittiosex rader? Om svaret är ja behöver du köra BIGINT, annars inte.
Indexering på [VAR]CHARS (du vill troligtvis använda CHAR till en sträng med fast längd) ska inte bli direkt långsammare, jag gissar att databasen bygger upp någon sorts hashmap i bakgrunden. Däremot tar det ju extra utrymme och innebär overhead när hash-värdet för en rad ska räknas ut i samband med INSERT.

Haha, när du skriver det sådär så är det ju onekligen så att det verkar aningen för mycket. Fyra miljarder is the shit.

EDIT: Det är med unsigned du räknar då, antar jag? Annars så går det väl från -2^31 till +2^31?

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Citat:

When an AUTO_INCREMENT column runs out of values, InnoDB wraps a BIGINT to -9223372036854775808 and BIGINT UNSIGNED to 1. However, BIGINT values have 64 bits, so if you were to insert one million rows per second, it would still take nearly three hundred thousand years before BIGINT reached its upper bound.

Källa: MySQL :: MySQL 5.0 Reference Manual :: 13.2.14 Restrictions on InnoDB Tables

Nog för att Teknocide talade klarspråk. Jag ville bara komma med en officiell källa på hur stor en BIGINT faktiskt är.

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Medlem
Skrivet av Christhebalrog:

Hej!

Har funderat lite på vad som är smidigast att använda som unique id i mysql-databaser?

*Smidigast* ÄR att använda en numretisk columntyp som du kan göra auto increment på. Ska du hitta på något mer *osmidigt* kommer du själv få sköta kollissionshantering/uppräkning osv. Kan det vara så att du tycker det ser tuffare/mer ELiTE ut med hex?

Permalänk
Medlem

Först ska du nog fundera på varför du inte vill ha en int som primary key, och vad det är du vill ha istället.

Men även om du är säker på din sak känns inte CHAR som rätt typ att spara i. Bara namnet på typen får varningsklockorna att ringa, du vill ju inte spara ner ett ord eller en lista på bokstäver, utan det du vill spara är någonting annat, ett ID. Typen på kolumnen ska säga vad den innehåller om möjligt och i det här fallet finns bättre alternativ.

CHAR är inte bra därför att den dels uppmuntrar att du sparar ner din hex-sträng som en sträng, tex 'AFCD' i en CHAR(4) och det vore ju väldigt onödigt prestanda och platsmässigt så det hoppas jag inte någon som pratade om CHARs tänkte föreslå

Om du istället sparar ner hexen som sina värden, dvs i mitt AFCD-exempel talet 45005, i en CHAR(2) så får du andra jobbiga problem. Sätter du inte binary som collation/charset på CHAR-kolumnen så är det bäddat för problem, ganska jobbigt om tex collation-inställningen är en som inte gör skillnad på A och a... Eller det faktum att du inte kan ge IDt till en annan person utan att se till att även den personen har rätt collation i databasen. Eller att om du skickar in 'AF' till en CHAR(4) så lägger MySQL in mellanslag istället för 0or för att fylla ut till 4 bytes.

Istället kan du använda BINARY. Eller så är det helt enkelt enklare med en int eller bigint om du inte kan komma på någon bra anledning till att ha något större än 64 bitar

(ska påpeka att jag mest använder MSSQL så ta inlägget med en nypa salt och rätta mig om jag har fel)

Visa signatur

AK47s for everyone! - Angry mob
Since NaN /= NaN, I think, we should decipher 'NaN' as 'Not a NaN' - Miguel Mitrofanov
(Varför är människan så benägen att tro på Gud?) Antagligen har det lönat sig och evolutionen har drivit fram sådana hjärnor. - Anon

Permalänk
Skrivet av Leedow:

Källa: MySQL :: MySQL 5.0 Reference Manual :: 13.2.14 Restrictions on InnoDB Tables

Nog för att Teknocide talade klarspråk. Jag ville bara komma med en officiell källa på hur stor en BIGINT faktiskt är.

Haha, du har alldeles rätt!

Skrivet av iXam:

*Smidigast* ÄR att använda en numretisk columntyp som du kan göra auto increment på. Ska du hitta på något mer *osmidigt* kommer du själv få sköta kollissionshantering/uppräkning osv. Kan det vara så att du tycker det ser tuffare/mer ELiTE ut med hex?

Nej, det har inget med att det ser "tuffare" ut. Min far jobbar nämligen med databaser i ganska stor skala (affärssystem och transaktionssystem) och vad jag har sett så kör de med "unique identifier" istället för auto-inc int. Antar att det finns en anledning till detta. Sedan kör de ju inte mysql i produktionsmiljöerna, tror det är oracle som är den stora hos dem.

Skrivet av vb:

Först ska du nog fundera på varför du inte vill ha en int som primary key, och vad det är du vill ha istället.

Men även om du är säker på din sak känns inte CHAR som rätt typ att spara i. Bara namnet på typen får varningsklockorna att ringa, du vill ju inte spara ner ett ord eller en lista på bokstäver, utan det du vill spara är någonting annat, ett ID. Typen på kolumnen ska säga vad den innehåller om möjligt och i det här fallet finns bättre alternativ.

CHAR är inte bra därför att den dels uppmuntrar att du sparar ner din hex-sträng som en sträng, tex 'AFCD' i en CHAR(4) och det vore ju väldigt onödigt prestanda och platsmässigt så det hoppas jag inte någon som pratade om CHARs tänkte föreslå

Om du istället sparar ner hexen som sina värden, dvs i mitt AFCD-exempel talet 45005, i en CHAR(2) så får du andra jobbiga problem. Sätter du inte binary som collation/charset på CHAR-kolumnen så är det bäddat för problem, ganska jobbigt om tex collation-inställningen är en som inte gör skillnad på A och a... Eller det faktum att du inte kan ge IDt till en annan person utan att se till att även den personen har rätt collation i databasen. Eller att om du skickar in 'AF' till en CHAR(4) så lägger MySQL in mellanslag istället för 0or för att fylla ut till 4 bytes.

Istället kan du använda BINARY. Eller så är det helt enkelt enklare med en int eller bigint om du inte kan komma på någon bra anledning till att ha något större än 64 bitar

(ska påpeka att jag mest använder MSSQL så ta inlägget med en nypa salt och rätta mig om jag har fel)

Jag är nog relativt övertygad nu i alla fall. Jag kör på int som primary key. Skulle det otroliga hända, att jag får problem med för lite rader så är det ett senare problem. Mycket senare problem...

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Skrivet av Christhebalrog:

Nej, det har inget med att det ser "tuffare" ut. Min far jobbar nämligen med databaser i ganska stor skala (affärssystem och transaktionssystem) och vad jag har sett så kör de med "unique identifier" istället för auto-inc int. Antar att det finns en anledning till detta. Sedan kör de ju inte mysql i produktionsmiljöerna, tror det är oracle som är den stora hos dem.

Då tycker jag du ska fråga honom om detta. Och du får gärna rapportera tillbaka här med en förklaring för jag är nyfiken.

Sen kan det ju vara så att UI (eller GUI) har sin plats om det är så att flera databaser snabbt ska kunna spara en vissa data och ändå kunna indexera dessa unikt.

Ett databasschema/setup skiljer ju sig lite från "Jockes" CS-clansida mot en internationell banks

Permalänk

Dom använder nog GUID då... En ganska bra anledning till detta är att man kan skapa unika nycklar och använda dessa direkt vid klienten utan att behöva anropa databasen. Då kan man även optimera INSERT på relationer en hel del.

T.ex:

INSERT INTO [Users] ([Id], [Username]) VALUES ('000000-0000-0000-000000', 'Username'); INSERT INTO [Posts] ([Id], [User], [Text]) VALUES ('000000-0000-0000-000000', '000000-0000-0000-000000', 'Kalle Erik Petter');

Gentemot:

DECLARE @UserId INTEGER; INSERT INTO [Users] ([Username]) VALUES ('Username'); SET @UserId = SCOPE_IDENTITY(); INSERT INTO [Posts] ([User], [Text]) VALUES (@UserId, 'Kalle Erik Petter');

Kanske inte riktigt visar fördelen iofs... Men tänk dig att du ska spara ner en herarki på 1000-2000 objekt. Det blir GANSKA många frågor mot databasen. Kör man exempelvis en ORM så kan det handla om ÄNNU fler frågor.

En till fördel är att man kan cacha framtida frågor, t.ex så kan du vänta tills du har 10,000 objekt att spara innan du frågar databasen.

Detta går även att ordna med Hi/Lo-algoritmen som använder vanliga siffror.

Permalänk
Skrivet av iXam:

Då tycker jag du ska fråga honom om detta. Och du får gärna rapportera tillbaka här med en förklaring för jag är nyfiken.

Sen kan det ju vara så att UI (eller GUI) har sin plats om det är så att flera databaser snabbt ska kunna spara en vissa data och ändå kunna indexera dessa unikt.

Ett databasschema/setup skiljer ju sig lite från "Jockes" CS-clansida mot en internationell banks

Svaret är helt enkelt att en UUID/GUID genereras för att vara unik "i tid och rum", det vill säga att det är i princip omöjligt att generera den igen (vilket inte är fallet med INT). Detta hade fördelar när man arbetar med många och stora databaser, då man ofta har många olika tabeller vars nycklar helt enkelt måste vara unika. I fallet med integer blir ju dessa inte unika då du i så fall börjar på 1 i varje ny tabell.

Skrivet av hagbarddenstore:

Dom använder nog GUID då... En ganska bra anledning till detta är att man kan skapa unika nycklar och använda dessa direkt vid klienten utan att behöva anropa databasen. Då kan man även optimera INSERT på relationer en hel del.

T.ex:

INSERT INTO [Users] ([Id], [Username]) VALUES ('000000-0000-0000-000000', 'Username'); INSERT INTO [Posts] ([Id], [User], [Text]) VALUES ('000000-0000-0000-000000', '000000-0000-0000-000000', 'Kalle Erik Petter');

Gentemot:

DECLARE @UserId INTEGER; INSERT INTO [Users] ([Username]) VALUES ('Username'); SET @UserId = SCOPE_IDENTITY(); INSERT INTO [Posts] ([User], [Text]) VALUES (@UserId, 'Kalle Erik Petter');

Kanske inte riktigt visar fördelen iofs... Men tänk dig att du ska spara ner en herarki på 1000-2000 objekt. Det blir GANSKA många frågor mot databasen. Kör man exempelvis en ORM så kan det handla om ÄNNU fler frågor.

En till fördel är att man kan cacha framtida frågor, t.ex så kan du vänta tills du har 10,000 objekt att spara innan du frågar databasen.

Detta går även att ordna med Hi/Lo-algoritmen som använder vanliga siffror.

Precis, där ligger förmodligen också en del. Som jag har förstått det så genereras UUID/GUID utifrån unix-timestamp, randomnummer (frö) och datorns id (typ ethernet-mac). Även om sannolikheten finns att denna 128-bitars nyckel inte skulle vara unik (även i en enorm databas), är den nog i likhet med att hitta ett riskorn i vårt solsystem...

Kan även tillägga att jag nu på nytt bestämt mig för att använda UUID istället för INT som primärnycklar.

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Skrivet av Christhebalrog:

Kan även tillägga att jag nu på nytt bestämt mig för att använda UUID istället för INT som primärnycklar.

Varför? Vad för slags app/db är det du fnular på?

Permalänk
Skrivet av iXam:

Varför? Vad för slags app/db är det du fnular på?

Av den enkla anledningen att med UUID så blir nyckeln unik i hela databasen istället för bara i tabellen.

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Skrivet av Christhebalrog:

Av den enkla anledningen att med UUID så blir nyckeln unik i hela databasen istället för bara i tabellen.

Vilka fördelar ger det dig?
edit: ok, jag läste ovan. Gör som du tycker är bäst; personligen skulle jag använt INTs på grund av snabbhet och enkelhet.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Teknocide:

Vilka fördelar ger det dig?
edit: ok, jag läste ovan. Gör som du tycker är bäst; personligen skulle jag använt INTs på grund av snabbhet och enkelhet.

När det gäller snabbhet så är kanske INT snabbare (borde ju vara), men jag tror inte det handlar om direkt långa fördröjningar. Vore ju trevligt att se siffror på detta. Som det är nu lagrar jag nyckeln i en CHAR(36), vilket egentligen är INT med en annan formatering. Vet dock inte hur databasen i sig lagrar det, det skiljer nog mellan olika databasmotorer...

Jag vet inte om det är så mycket mer enkelt att använda auto-inc INT. Som det är nu så har jag möjlighet att skapa UUID via programkoden (Java) alternativt direkt i databasanropet (mha funktionen UUID()). Plus att vid många tabeller behöver man inte oroa sig för dryga databasfel som uppstå pga att man förväxlat två tabellers id, vilket i fallet med INT resulterar i ett felaktigt svar (eftersom id:t med största sannolikhet existerar i båda tabeller)

Funderar dock på vad som är smidigast att spara UUID:er som i databasen? Jag använder, som jag tidigare nämnt, CHAR(36) för att det är en "primitiv datatyp" (iaf inom många programspråk) så det borde inte vara så mycket over-head. Nån som har koll på detta?

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem

CHAR(36) sparas som en trettiosex tecken lång sträng. Om vi antar att varje tecken är en byte har vi alltså en minnesstruktur som är nio gånger större än en INT. För att väga två strängar mot varandra jämförs tecken för tecken. Dvs. 36 jämförelser vs. en jämförelse för INT.

Den verkliga kickern är dock "dryga databasfel". Jag förstår inte vad du menar alls här: Om du "råkar" jämföra två helt orelaterade tabeller så är problemet större än att ID:n krockar med varandra. Varför, och hur, skulle två okompatibla tabeller kunna komma att jämföras med varandra? Varför är det positivt att det inte blir ID-krockar om jämförelsen är ett resultat av felaktig query, men främst, vad är fördelen med att ha globalt unika ID:n över en mängd tabeller? En primärnyckel SKA finnas i andra tabeller -- det är så man knyter dem samman.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

*Suckar* Du går alltså helt mot strömmen och väljer en teknik som för dig inte har några som helst fördelar utan endast nackdelar FÖR DIG och dessutom gör du det på ett förkastligt sätt genom att lagra nyckeln i HEX-representation.
Jag lämnar denna tråden eftersom trådskaparen inte verkar ha förmågan eller viljan att ta till sig verklig information och baserar sina antaganden på ren okunskap.
Ex :

Skrivet av Christhebalrog:

Plus att vid många tabeller behöver man inte oroa sig för dryga databasfel som uppstå pga att man förväxlat två tabellers id, vilket i fallet med INT resulterar i ett felaktigt svar (eftersom id:t med största sannolikhet existerar i båda tabeller)

Hur i helskotta tänker du här? Förväxlar du två tabellers IDn så har du ju tänkt fel från början. Har du ingen relationsdatabas utan kastar bara in så mycket ostrukturerad data du kan komma över? Har du ingen relationsdatabas så finns det andra bättre metoder att lagra din data.
Du har även inte berättat vad det är du utvecklar vilket får mig att tro att du bara labbar och tja, då torde du ju labba (benchmarka) för och nackdelarar med dina metoder istället för att blint välja den felaktiga.

Permalänk
Skrivet av Teknocide:

CHAR(36) sparas som en trettiosex tecken lång sträng. Om vi antar att varje tecken är en byte har vi alltså en minnesstruktur som är nio gånger större än en INT. För att väga två strängar mot varandra jämförs tecken för tecken. Dvs. 36 jämförelser vs. en jämförelse för INT.

Den verkliga kickern är dock "dryga databasfel". Jag förstår inte vad du menar alls här: Om du "råkar" jämföra två helt orelaterade tabeller så är problemet större än att ID:n krockar med varandra. Varför, och hur, skulle två okompatibla tabeller kunna komma att jämföras med varandra? Varför är det positivt att det inte blir ID-krockar om jämförelsen är ett resultat av felaktig query, men främst, vad är fördelen med att ha globalt unika ID:n över en mängd tabeller? En primärnyckel SKA finnas i andra tabeller -- det är så man knyter dem samman.

Det blir fler jämförelser, det är sant.

Håller med om att argumentet om "dryga databasfel" var lite missvisande. Det jag menar var ifall du har flera tabeller ihopkopplade och varje tabell har ett enskilt nummer kopplat till sig (som återfinns i andra tabeller) så kan det enklare uppstå "felkopplingar" vid t.ex. sammanslagning av tabeller. Då uppkommer problemet att du får samma ID på två ställen som refererar till olika poster. Detta blir inte fallet med UUID, då den är universiellt unik.

Detta är förmodligen även en av anledningarna till att auto-inc INT inte används ute i de större databaserna.

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem

Klart att INT används i stora databassystem; det är det mest felsäkra och effektivaste sättet att unikt identifiera en rad i en databastabell. Beroende på typen av tabell är det förvisso ibland lämpligare att att använda en annan sorts primärnyckel.

Vid JOINs kommer ditt scenario aldrig att uppstå. Endast när två separata databaser med identiska tabeller -- exempelvis en databas som relativt nyligen tömts omskapats och en tidigare backup med samma tabellstruktur -- ska kombineras får man nyckelkollisioner.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Skrivet av Teknocide:

Klart att INT används i stora databassystem; det är det mest felsäkra och effektivaste sättet att unikt identifiera en rad i en databastabell. Beroende på typen av tabell är det förvisso ibland lämpligare att att använda en annan sorts primärnyckel.

Vid JOINs kommer ditt scenario aldrig att uppstå. Endast när två separata databaser med identiska tabeller -- exempelvis en databas som relativt nyligen tömts omskapats och en tidigare backup med samma tabellstruktur -- ska kombineras får man nyckelkollisioner.

Det är möjligt att det används i stora databassystem. De enda större databassystem jag har någon insyn i är de min pappa jobbar med (MIO, LKAB, Getinge, etc) och där används GUID istället för INT, och som jag förstod det så är det där mycket viktigt att varje rad i varje tabell är given ett globalt unikt värde, eftersom det oftast är flera databaser inblandade som sköter samma typ av transaktioner.

Ta t.ex. ett kassasytem för ett stort företag. För att klara den enorma mängden transaktioner som genomförs per dag måste det spridas på flera databaser. Kan tänka mig kanske 1 per varuhus. När dessa sedan skickas till "huvudkontorets" databas för att sammanställa dagens försäljning, så hade det blivit extremt knepigt ifall det hade kommit 2 miljoner rader med samma tabell-id fast med olika innehåll. Detta problemet löses med UUID eftersom det genereras delvis mha datorns MAC-adress. Resultatet blir att alla 2 miljoner raderna är unika, och kan migreras utan vidare behandling. - Man sparar tid här, men förlorar tid vid insättningen i tabellen.

Notera att jag inte säger att auto-inc int är dåligt på något sätt. Det, liksom UUID har sina fördelar och nackdelar. I ett mindre projekt (som t.ex. mitt i detta fallet) där man bara har en databas inblandad så finns det kanske ingen praktisk anledning att använda något annat än auto-inc int. Samtidigt så blir det inga större förluster att använda UUID när det handlar om så små volymer.

Anledningen till att jag väljer UUID är för att jag lätt vill kunna delegera arbetet på flera (och olika) databaser, t.ex. X10, MS SQL, postgreSQL, MySql, DB2, m.fl. Det är alltså i rent "utbildningssyfte", och inte en ren prestandaåtgärd.

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W

Permalänk
Medlem
Skrivet av Christhebalrog:

När det gäller snabbhet så är kanske INT snabbare (borde ju vara), men jag tror inte det handlar om direkt långa fördröjningar. Vore ju trevligt att se siffror på detta. Som det är nu lagrar jag nyckeln i en CHAR(36), vilket egentligen är INT med en annan formatering. Vet dock inte hur databasen i sig lagrar det, det skiljer nog mellan olika databasmotorer...

Jag vet inte om det är så mycket mer enkelt att använda auto-inc INT. Som det är nu så har jag möjlighet att skapa UUID via programkoden (Java) alternativt direkt i databasanropet (mha funktionen UUID()). Plus att vid många tabeller behöver man inte oroa sig för dryga databasfel som uppstå pga att man förväxlat två tabellers id, vilket i fallet med INT resulterar i ett felaktigt svar (eftersom id:t med största sannolikhet existerar i båda tabeller)

Funderar dock på vad som är smidigast att spara UUID:er som i databasen? Jag använder, som jag tidigare nämnt, CHAR(36) för att det är en "primitiv datatyp" (iaf inom många programspråk) så det borde inte vara så mycket over-head. Nån som har koll på detta?

En CHAR(36) tar dubbelt så mycket plats som en binary(16) (minsta typen där en 128-bitars UUID får plats) så jag skulle inte kalla den effektiv direkt.. Om du kodar för att lära dig tycker jag helt klart du ska köra på binary.

Googlar man på uuid så kommer den här artikeln upp i toppen typ: http://www.mysqlperformanceblog.com/2007/03/13/to-uuid-or-not... Enligt den gick det 200 gånger långsammare med CHAR(36) än med autoincrement int.

Visa signatur

AK47s for everyone! - Angry mob
Since NaN /= NaN, I think, we should decipher 'NaN' as 'Not a NaN' - Miguel Mitrofanov
(Varför är människan så benägen att tro på Gud?) Antagligen har det lönat sig och evolutionen har drivit fram sådana hjärnor. - Anon

Permalänk
Medlem
Skrivet av Christhebalrog:

CHAR(36), vilket egentligen är INT med en annan formatering.

Nej, det är det inte.

Skrivet av Christhebalrog:

Plus att vid många tabeller behöver man inte oroa sig för dryga databasfel som uppstå pga att man förväxlat två tabellers id

Om det händer så har du gjort fel. Ger man sina tabeller unika deskriptiva namn så händer inte det här. Ser man dessutom till att inte köra e.g. "SELECT *" utan specificerar kolumnerna man vill ha så händer det garanterat inte, förutsatt att man har en någorlunda vettig databasstruktur.

Skrivet av Christhebalrog:

Ta t.ex. ett kassasytem för ett stort företag. För att klara den enorma mängden transaktioner som genomförs per dag måste det spridas på flera databaser. Kan tänka mig kanske 1 per varuhus. När dessa sedan skickas till "huvudkontorets" databas för att sammanställa dagens försäljning, så hade det blivit extremt knepigt ifall det hade kommit 2 miljoner rader med samma tabell-id fast med olika innehåll. Detta problemet löses med UUID eftersom det genereras delvis mha datorns MAC-adress. Resultatet blir att alla 2 miljoner raderna är unika, och kan migreras utan vidare behandling. - Man sparar tid här, men förlorar tid vid insättningen i tabellen.

Det här är bara relevant när du har flera olika databaser som du rutinmässigt mergear. är det, som du säger, viktigt att IDn inte krockar. Men mellan tabeller spelar det ingen roll, och ska man inte lägga ihop databaser på det här sättet finns det ingen större anledning att använda UUID.

Permalänk
Skrivet av vb:

En CHAR(36) tar dubbelt så mycket plats som en binary(16) (minsta typen där en 128-bitars UUID får plats) så jag skulle inte kalla den effektiv direkt.. Om du kodar för att lära dig tycker jag helt klart du ska köra på binary.

Googlar man på uuid så kommer den här artikeln upp i toppen typ: http://www.mysqlperformanceblog.com/2007/03/13/to-uuid-or-not... Enligt den gick det 200 gånger långsammare med CHAR(36) än med autoincrement int.

Tackar för det. Skall kolla lite extra på det med binary, det verkar onekligen värt att läsa på mer om!

Skrivet av You:

Nej, det är det inte.

Inom vanlig programmering kan du ju casta mellan INT och CHAR utan vidare. Jag antog att man "sparade" de på samma sätt här.

Skrivet av You:

Om det händer så har du gjort fel. Ger man sina tabeller unika deskriptiva namn så händer inte det här. Ser man dessutom till att inte köra e.g. "SELECT *" utan specificerar kolumnerna man vill ha så händer det garanterat inte, förutsatt att man har en någorlunda vettig databasstruktur.

Absolut har man det. Se min tidigare post, jag menade vid migrering av databaser.

Skrivet av You:

Det här är bara relevant när du har flera olika databaser som du rutinmässigt mergear. är det, som du säger, viktigt att IDn inte krockar. Men mellan tabeller spelar det ingen roll, och ska man inte lägga ihop databaser på det här sättet finns det ingen större anledning att använda UUID.

Det är förmodligen av denna anledning som de kör uuid och inte auto-inc int. Men båda har, som sagt, sina fördelar. Allt beror ju på användningsområdet. UUID har väl sina starka fördelar vid många förfrågningar samtidigt, då ID:t kan skapas direkt i klienten, som nämndes tidigare.

Får kanske bestämma mig för att byta till auto-inc int Vi får se hur det blir. Såg att det fanns mycket att läsa om detta på nätet. Tydligen är det inte första gången frågan har dykt upp.

Visa signatur

Moderkort: Asus Z97-PRO CPU: Intel Core i7 4790K GPU: MSI GTX 980 Gaming
RAM: A-Data 2x8GB DDR3 Chassi: NZXT H400W