mini TYPES HowTo

PHPportalen Forum Index » Databaser
Lägg ett bokmärke på hela tråden
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2, 3  Nästa
Visa föregående ämne :: Visa nästa ämne  
Startad av: Meddelande
temptraq
Ex-Moderator



Medlem i: 5047 dagar
Från: Åkersberga
Status: Offline



#452769
Inlägg Skrivet: 2007-01-19 21:04      Ämne: mini TYPES HowTo Citera

Varje kolumn i en tabell måste deklareras till att innehålla en typ av data. Man måste också, oftast, bestämma kolumnens storlek. Genom att göra detta rätt från början sparar du utrymme, bandbredd och prestandan (hastigheten) ökar.

Grundläggande kan man säga att det finns fyra TYPES.

* tal
* text
* datum och tid
* listor

Därutöver finns det variationer inom dessa TYPES.

Heltal (integer)
TINYINT 1 byte MAX 127
SMALLINT 2 bytes MAX 32 767
MEDIUMINT 3 bytes MAX 8 388 607
INT 4 bytes MAX 2 147 783 647
BIGINT 8 bytes MAX 9 223 372 036 854 755 807

Standard är dessa SIGNED d.v.s. de ha lika stora negativa tal. T.ex. så kan TINYINT innehålla MIN -127 (HTML är avstängt så det är svårt att göra överskådliga tabeller...)
Genom att deklarera UNSIGNED så kan kolumnen inte innehålla negativa tal men i stället dubbelt så stort positivt tal. TINYINT UNSIGNED får då MAX 254

Citat:
Men om jag gör INT(3) så blir ju MAX 999

Nej, INT(3) kan fortfarande lagra MAX 2 147 783 647 och reserverar 4 bytes. 3:an bestämmer bara hur många tecken, minst, som ska visas. Detta förutsätter att kolumnen har attributet ZEROFILL. MySQL fyller alltså på med INLEDANDE nollor tills (3) har uppfyllts.
7 blir 007
77 blir 077
777 blir 777
77777777 blir 77777777

Hur ska man välja då?
Sunt förnuft är alltid bra! Ska du lagra skostorlekar kan du lugnt använda TINYINT, eller UNSIGNED TINYINT, eftersom ingen har över 127(254) i skostorlek. Är det månadslön du ska lagra så är väl MEDIUMINT lämpligt eftersom få personer tjänar över 8 388 607 i månaden. Här kan det dock vara smart att behålla SIGNED eftersom man faktiskt kan få löneavdrag.

På id-fält som har auto_increment måste man tänka ännu mer. En Tabell för folkbokföring kanske behöver INT medans en tabell som lagrar kommentarer i en blogg kanske klarar sig med TINYINT UNSIGNED.

Man kan alltid gå uppåt i värden med ALTER utan risk att förstöra data men inte ner. Så kommentartabellen som plötsligt ger ett felmeddelande kan man 'öka' till SMALLINT.

Decimaltal
*FLOAT
*DOUBLE
*DECIMAL

Dessa tre skiljer sig åt på två punkter,
nogrannhet och reserverat utrymme.

Om nogrannheten inte spelar någon roll, välj FLOAT.
FLOAT är osäkert efter åttonde decimalen men reserverar 'bara' 4 bytes.
Citat:
Åtta decimaler? Det använder väl ingen...

Nej, inte normalt. Men i t.ex funktioner med AVG() och all division så kan det spela roll.

DOUBLE är, ungefär, 10^10 gånger nogrannare än FLOAT och använder 8 bytes.

DECIMAL liknar DOUBLE men man definerar dels längd, dels antal siffror till höger om decimaltecknet (DECIMAL(5,2)). Användbart när man vill ha ett bestämt antal decimaler (pris t.ex.)

text
*CHAR 0 till 255 tecken
CHAR är till för textsträngar med bestämd längd. CHAR(40) reserverar 40 bytes oavsett vad du sparar i kolumnen. Exempel på värden med bestämd läng är t.ex. personnummer, ISBN-nummer, postnummer.

*VARCHAR 1 till 255 tecken
VARCHAR är till för textsträngar vars längd man inte känner till. Fördelen gentemot CHAR är att VARCHAR reserverar antal tecken i bytes + en byte för längden. Nackdelen är att sökning går långsammare eftersom längden varierar, potentiellt, för varje rad. Definitionen VARCHAR(50) innebär att ingen textsträng är längre än 49 tecken (1 byte till strl.)

**** TIPS ****
Loggar du IP-adresser? VARCHAR(15)?
Lagra som INT UNSIGNED i stället och spara utrymme. Hur?
Kör INET_ATON('213.200.164.249') så blir det 2147483647 och för att få tillbaka kör man INET_NTOA(2147483647)
*************


* TEXT och BLOB
TEXT och BLOB är samma sak med den skillnaden att BLOB-fält är CASE-Sensitive när man sorterar (ORDER BY).
CHAR och VARCHAR är inte heller CASE-Sensitive men man kan definera dem som det genom attributet BINARY.
-TINYTEXT och TINYBLOB 255 tecken (reserverar längd +1 byte)
-TEXT och BLOB 65 535 tecken (reserverar längd +2 byte)
-MEDIUMTEXT och MEDIUMBLOB 16 777 215 tecken (reserverar längd +3 byte)
-LONGTEXT och LONGBLOB 4 294 967 295 tecken (reserverar längd +4 byte)

Använd sunt förnuft här också.


Datum och Tid
Glöm inte att detta är strängar och ska alltså skrivas '2007-01-21'.
Gäller inte TIMESTAMP

* DATE
Lagrar ett kalenderdatum i formatet YYYY-MM-DD.

* TIME Lagrar ett klockslag (timer) i formatet (24h) HHH:MM:SS. Den inledande o:an visas inte när HHH är mindre än 100.

* YEAR
Lagrar fyrsiffrigt årtal.

* DATETIME
Lagrar ett komplett kalenderdatum och tid i formatet YYYY-MM-DD HH:MM:SS.

* TIMESTAMP
Lagrar UNIX TIMESTAMP (antal sekunder från 1970-01-01 00:00:00, enligt serverklockan).

**** TIPS ****
Undvik att använda TIMESTAMP. Behöver du UNIX TIMESTAMP till en funktion eller klass så lagra det som en INT mha MySQL-funktionen UNIX_TIMESTAMP.
*************

DATE och TIME resreverar 3 bytes, YEAR bara 1 byte och DATETIME 8 bytes. Så det finns mycket plats att spara genom att göra 'rätt'.

För samtliga typer gäller att om du skickar in NOW() så lagras datumet, klockslaget, året eller datum och klockslag enligt kolumnens format.

För att sedan bearbeta, jämföra och extrahera värden finns en hel massa inbyggda funktioner, t.ex. DATE_FORMAT,DATE_ADD och DATE_SUB.

ENUM och SET

* ENUM
Är MySQL's motsvarighet till 'radioknapp'. Kolumnen kan anta ett värde från en lista. Orderstatus är ett bra exempel. Ange i definitionen att kolumnen får anta dessa värden: 'Mottagen', 'Bekräftad', 'Skickad' , 'Fakturerad'. En annan lösning vore ju att skapa fyra separata kolumner för dessa värden och sedan använd '0' och '1' för att veta var i kedjan ordern befinner sig.
Det är lite speciellt att använda ORDER BY och WHERE mot ENUM-kolumner. Läs dokumentationen. Jag kommer förmodligen ta upp det här, men lite senare.

* SET
Är MySQL's motsvarighet till 'kryssrutor'. Kolumnen kan anta ett, eller flera, värden från en lista. En speciell egenskap hos SET gör den till den minst använda typen men också till den potentiellt mest användbara.
Värden lagras som strängar men behandlas som heltal (indexeras BINÄRT).
Man kan tänka sig en lista på vilka språk/tekniker någon behärskar:
'PHP','JavaScript','CSS','DHTML'.
Även om man lagrar dem i olika ordning för alla personer så kommer MySQL att i en SELECT sortera dem enligt din lista. Det går också bra att använda LIKE (SELECT * FROM table WHERE experience LIKE '%PHP%CSS%') för att på så sätt få veta vem/vilka som både PHP och CSS.

Mer om heltal och binär lagring kommer.

Senast ändrad av temptraq den 2007-11-15 10:22, ändrad totalt 1 gång
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
ErikW



Medlem i: 3938 dagar
Från: Linköping
Status: Offline



#473163
Inlägg Skrivet: 2007-03-27 14:18      Ämne: Citera

Intressant!
 

_________________
Www.superstart.inc.se
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida MSN Messenger
froppe



Medlem i: 4230 dagar

Status: Offline



#473361
Inlägg Skrivet: 2007-03-28 00:04      Ämne: Citera

Väldigt bra skrivet måste jag säga. Väldigt användbar information. Fortsätt i den här stilen.. Mycket bra jobbat..

Riktigt j'vla nice. F'n va du är grym..


ps. Ursäkta språket kunde inte skriva på nått annat sätt
 

_________________
Hjälp mig..
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
lord mazdak



Medlem i: 4816 dagar
Från: Göteborg
Status: Offline



#473527
Inlägg Skrivet: 2007-03-28 17:52      Ämne: Re: mini TYPES HowTo Citera

temptraq skrev:
Man måste också, oftast, bestämma kolumnens storlek. Genom att göra detta rätt från början sparar du utrymme, bandbredd och prestandan (hastigheten) ökar.


Gäller bara för Integer typer:
Vill bara poängtera att hastigheten ökar på överförningen mellan MySQL server -> Klient ( PHP scriptet, mm...).

Men internt hos MySQL går det långsammare (vi pratar micro/nanosekunder) beroende på hur din processorarkitektur ser ut.
Alltså om den är 32-bits / 16-bits eller 64-bits.
Antag att vi sitter på en burk med IA_32 processorarkitektur.
Använder du din processorarkitekturs standard integer storlek ( IA_32 har 4 bytes -> 32 bits ) så kommer det garanterat gå snabbast.
Det kan gå långsammare eller lika snabbt att använda TINYINT, SMALLINT, MEDIUMINT som/än en INT.

Men sannorlikt tar överförningen från MySQL server -> Klient längre tid bara för att du använder en INT istället för en TINYINT, så du vinner ändå i det stora hela på att använda en TINYINT
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida MSN Messenger
temptraq
Ex-Moderator



Medlem i: 5047 dagar
Från: Åkersberga
Status: Offline



#473636
Inlägg Skrivet: 2007-03-28 22:06      Ämne: Citera

lord mazdak, jag spenderade en hel del tid på att undersöka just detta och svaret jag fick var:
Citat:
Computation is always done using signed 64bit integer in MySQL (even for 32bit)

Säger inte att du har fel, bara att jag tittat på just det också.
Men som du nämner så är ju vinsten/förlusten så liten att det aldrig kommer att ha någon, praktisk, betydelse.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
solomon



Medlem i: 4781 dagar
Från: Solen
Status: Offline



#473663
Inlägg Skrivet: 2007-03-29 01:09      Ämne: Citera

Varför skall man undvika TIMESTAMP?
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
temptraq
Ex-Moderator



Medlem i: 5047 dagar
Från: Åkersberga
Status: Offline



#473688
Inlägg Skrivet: 2007-03-29 08:29      Ämne: Citera

Citat:
The TIMESTAMP data type has varying properties, depending on the MySQL version and the SQL mode the server is running in.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
solomon



Medlem i: 4781 dagar
Från: Solen
Status: Offline



#473768
Inlägg Skrivet: 2007-03-29 14:25      Ämne: Citera

temptraq skrev:
Citat:
The TIMESTAMP data type has varying properties, depending on the MySQL version and the SQL mode the server is running in.


Det var en ganska blek förklaring tycker jag nog.. Lite bättre kan du väl?
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
temptraq
Ex-Moderator



Medlem i: 5047 dagar
Från: Åkersberga
Status: Offline



#473773
Inlägg Skrivet: 2007-03-29 14:48      Ämne: Citera

Nä, jag tycker att det räcker som argument.
Om det behövs funktionallitet för att uppnå funktionallitet beroende på vilken version som är installerad tycker jag att man lika gärna kan använda något som fungerar oavsett version.

Men, det är bara ett tips -får Du det att fungera i Din lösning så fortsätt med det.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Malte
in memoriam 1



Medlem i: 5726 dagar
Från: Tingsryd
Status: Offline



#473849
Inlägg Skrivet: 2007-03-29 18:39      Ämne: Citera

Vad mer än utdata är det det skiljer sig på?
Finessen med TIMESTAMP är ju att den uppdaterar sig själv varje gång en ändring sker i kolumnen.
För ORDER BY har det ingen betydelse.
Och skulle man vilja ha ut datumet så kan man för säkerhets skull använda DATE_FORMAT().

Jag måste också erkänna att det var en överraskning när TIMESTAMP bytte format i MySQL Smile
 

_________________
Funktion är vackert
Till toppen på sidan
Visa användarprofil Besök användarens hemsida
solomon



Medlem i: 4781 dagar
Från: Solen
Status: Offline



#473854
Inlägg Skrivet: 2007-03-29 18:48      Ämne: Citera

temptraq skrev:
Nä, jag tycker att det räcker som argument.
Om det behövs funktionallitet för att uppnå funktionallitet beroende på vilken version som är installerad tycker jag att man lika gärna kan använda något som fungerar oavsett version.

Men, det är bara ett tips -får Du det att fungera i Din lösning så fortsätt med det.


Malte skrev:
Vad mer än utdata är det det skiljer sig på?
Finessen med TIMESTAMP är ju att den uppdaterar sig själv varje gång en ändring sker i kolumnen.
För ORDER BY har det ingen betydelse.
Och skulle man vilja ha ut datumet så kan man för säkerhets skull använda DATE_FORMAT().

Jag måste också erkänna att det var en överraskning när TIMESTAMP bytte format i MySQL Smile


Det finns mycket med TIMESTAMP som har sina fördelar i rätt tillfälle och bara för att formatet på utskriften (default) ändrat sig (till det bättre eftersom det är enklare att läsa "rådatan") så tycker jag inte att det är skäl nog att säga att man skall undvika den. Sen precis som Malte säger så är det smidigt att den uppdaterar sig själv vid senaste uppdateringen om man vill det.

Den som tidigare använde TIMESTAMP för att få ut 20070328184600 tycker jag snarare var fel ute när dom inte använde DATE_FORMAT(col, '%Y%m%d%H%i%s') oavsett vilken typ av kolumn det var.

Att välja mellan att köra

SELECT * FROM x WHERE TIMEDIFF(NOW(), UNIX_TIMESTAMP(intcol)) > '00:10:00'

och

SELECT * FROM x WHERE TIMEDIFF(NOW(), timestampcol) > '00:10:00'


(alt. med INTERVAL)

så blir det absolut det senare och dessutom kan man fortfarande vara glad den dagen någon klantig människa skulle få för sig att ställa in rätt timezone efter att den varit felaktig en längre tid (mindre troligt i.o.f.s.).

Både TIMESTAMP och INT tar upp 4 bytes så där finns det inget att klaga på, men att behöva konvertera med UNIX_TIMESTAMP så fort man vill göra något tycker jag är overkill.

edit: tog bort aliaset..

Senast ändrad av solomon den 2007-03-29 23:46, ändrad totalt 1 gång
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
temptraq
Ex-Moderator



Medlem i: 5047 dagar
Från: Åkersberga
Status: Offline



#473981
Inlägg Skrivet: 2007-03-29 23:38      Ämne: Citera

Som sagt, bara ett tips.
Nu kan alla läsare själva ta ställning till hur de vill lösa det i sin applikation.

ALLA vinner Smile
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
solomon



Medlem i: 4781 dagar
Från: Solen
Status: Offline



#474002
Inlägg Skrivet: 2007-03-30 01:52      Ämne: Citera

Citat:

Vad mer än utdata är det det skiljer sig på?
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
blomqvist



Medlem i: 4842 dagar
Från: Norrköping
Status: Offline



#498302
Inlägg Skrivet: 2007-06-20 21:57      Ämne: Citera

Otroligt matnyttigt.
Det här kommer jag absolut använda mig av. Tack!
 

_________________
mount -t spam /dev/spam /dev/null
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
lord mazdak



Medlem i: 4816 dagar
Från: Göteborg
Status: Offline



#501365
Inlägg Skrivet: 2007-07-04 12:01      Ämne: Citera

temptraq skrev:
lord mazdak, jag spenderade en hel del tid på att undersöka just detta och svaret jag fick var:
Citat:
Computation is always done using signed 64bit integer in MySQL (even for 32bit)

Säger inte att du har fel, bara att jag tittat på just det också.
Men som du nämner så är ju vinsten/förlusten så liten att det aldrig kommer att ha någon, praktisk, betydelse.


2000 år senare men, förstår inte varför MySQL skulle göra ett så stort misstag, kanske har att göra med att de slipper kolla efter vilken storlek som ska användas men det finns ju variabla Integer proxy classer man kan använda, kommer inte ihåg om MySQL va kodat i C eller C++ antar C men det finns ju sätt att fixa proxy classerna i C också.
Att beräkna integer typen som ska användas tar mycket mindre minne än att inte göra det
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida MSN Messenger
Visa tidigare inlägg:   
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2, 3  Nästa
PHPportalen Forum Index » Databaser
Hoppa till:  
Du kan inte skapa nya inlägg i det här forumet
Du kan inte svara på inlägg i det här forumet
Du kan inte ändra dina inlägg i det här forumet
Du kan inte ta bort dina inlägg i det här forumet
Du kan inte rösta i det här forumet
Du kan inte bifoga filer i detta forum
Du kan inte ladda ner filer från detta forum
Kontakta oss på adressen: info@phpportalen.net
Webbplatsen bygger i grunden på phpBB © 2001, 2002 phpBB Group

Modifieringar har senare gjorts i systemet av PHPportalen
Sid och logotypdesign skapad av Daren Jularic