Después de un receso, regreso con
nuevos artículos y durante este tiempo, les puedo comentar que he observado
diferentes BDs en las cuales usan versiones recientes de SQL SERVER y aun no
conocen los diferentes y nuevos tipos de datos que ofrece, esto servirá no solo
para ahorrar espacio en disco duro si no también para pasar o consumir menos
ancho de banda, cache del equipo, entre muchas otras cosas, sin más les
explicaré algunos nuevos tipos de datos que ofrecen las nuevas versiones.
INT o INTEGER
Como bien conocemos, guarda solo
enteros positivos o negativos, pero sabías que existe más de un tipo de dato
INT y que cada uno ocupa diferente espacio en disco duro? Bien, te dejo una
siguiente tabla extraída de la página de MSDN
Tipo de datos
|
Intervalo
|
Almacenamiento
|
bigint
|
De -2^63
(-9.223.372.036.854.775.808) a 2^63-1 (9.223.372.036.854.775.807)
|
8 bytes
|
int
|
De -2^31
(-2.147.483.648) a 2^31-1 (2.147.483.647)
|
4 bytes
|
smallint
|
De -2^15 (-32.768) a
2^15-1 (32.767)
|
2 bytes
|
tinyint
|
De 0 a 255
|
1 byte
|
El tipo de dato TINYINT, solo
almacena números positivos como podemos observar en la tabla y solo ocupa 1
byte de espacio, pero se preguntarán sobre algún caso en la vida real en la
cual se pudiera utilizar dicho tipo de dato, pues bien, un ejemplo claro sería
la edad, o no? Si comparamos un tipo de dato INT con el tipo TINYINT para
alguien que tiene una edad de 50, no es lo mismo que en disco duro ocupe o que
pasen por la red 4 bytes, a que sea solo 1 byte, pero que pasaría si tuviéramos
una tabla con 1 millón de filas, estaríamos almacenando en disco duro y pasando
por la red 4,000,000 de bytes con el tipo de dato INT, mientras que con TINYINT
solo tendríamos 1,000,000 de bytes, veamos un ejemplo de esto, la primer tabla
muestra los extremos de los valores permitidos en cada columna así como si
almacenáramos un 1 en cada una de ellas.
DECLARE @tab TABLE( colBIGINT BIGINT , colINT INT , colSMALLINT SMALLINT , colTINYINT TINYINT ) INSERT INTO @tab VALUES( -9223372036854775808 , -2147483648, -32768, 0 ) , ( 1 , 1 , 1 , 1 ) , ( 9223372036854775807 , 2147483647 , 32767 , 255 ) SELECT * FROM @tab SELECT DATALENGTH( colBIGINT ) AS lnColBIGINT , DATALENGTH( colINT ) AS lnColINT , DATALENGTH( colSMALLINT ) AS lnColSMALLINT , DATALENGTH( colTINYINT ) AS lnColTINYINT FROM @tab
DECIMAL, NUMERIC.
Por lo general estamos
acostumbrados a usar el tipo de datos FLOAT, debemos de cambiar esa costumbre y
usar DECIMAL o NUMERIC, porque su precisión es más exacta que FLOAT o REAL,
observen el siguiente ejemplo:
DECLARE @tab TABLE ( colDECIMAL DECIMAL(20,10) , colNUMERIC NUMERIC(20,10) , colFLOAT FLOAT(10) , colREAL REAL ) INSERT INTO @tab VALUES( 1234567890.0123456789, 1234567890.0123456789 , 1234567890.0123456789 , 1234567890.0123456789 ) SELECT * , CAST( colFLOAT AS DECIMAL(20,10) ) , CAST( colREAl AS DECIMAL(20,10) ) FROM @tab
Y para el espacio en disco duro,
tenemos más amplia variedad de opciones a elegir de la cantidad de dígitos que
utilizaremos en DECIMAL y NUMERIC que en FLOAT y REAL, este ultimo no es
posible escoger la precisión, es equivalente a un FLOAT(24).
DECIMAL, NUMERIC.
Precisión
|
Bytes de
almacenamiento
|
1 - 9
|
5
|
10-19
|
9
|
20-28
|
13
|
29-38
|
17
|
FLOAT
Valor del
parámetro n
|
Precisión
|
Tamaño de
almacenamiento
|
1-24
|
7 dígitos
|
4 bytes
|
25-53
|
15 dígitos
|
8 bytes
|
REAL = FLOAT(24)
MONEY , SMALLMONEY
De la misma manera, es posible
almacenar valores tipo moneda, pero debemos poner mucha atención a la longitud
que utilizaremos, ya que tenemos dos opciones similares que pueden ocupar
diferente espacio en disco duro.
Tipo de datos
|
Intervalo
|
Almacenamiento
|
money
|
De -922,337,203,685,477.5808 a 922,337,203,685,477.5807
|
8 bytes
|
smallmoney
|
De - 214.748,3648 a 214.748,3647
|
4 bytes |
Veamos el siguiente ejemplo donde claramente podemos
observar cada uno de los tipos, así como el espacio en disco duro utilizado.
DECLARE @tab TABLE( colMONEY MONEY , colSMALLMONEY SMALLMONEY ) INSERT INTO @tab VALUES( 123456789123456.7891 , 123456.7891 ) , ( 1.1 , 1.1 ) , ( -123456789123456.7891 , -123456.7891 ) SELECT * FROM @tab SELECT DATALENGTH( colMONEY ) AS lnColMONEY , DATALENGTH( colSMALLMONEY ) AS lnColSMALLMONEY FROM @tab
TIPOS DE DATOS FECHA
En este rubro, tenemos varios
tipos los cuales debemos conocer para saber cual debemos utilizar de acuerdo al
rango que estemos manejando, veamos los tipos y el espacio ocupado en disco
duro.
DATE
El rango es de 0001-01-01 a 9999-12-31
con un espacio en disco duro de 3 bytes, no importa la fecha que se utilice de
ese rango:
DECLARE @tab TABLE( colDATE DATE ) INSERT INTO @tab VALUES( '00010101' ) , ( CAST( GETDATE() AS DATE ) ) , ( '99991231' ) SELECT *, DATALENGTH( colDATE ) AS lnColDate FROM @tab
DATETIME
El rango es de 1753-01-01 00:00:00.000 a 9999-12-31 23:59:59.997 con
un espacio en disco duro de 8 bytes, no importa la fecha que se utilice del
rango:
DECLARE @tab TABLE( colDATETIME DATETIME ) INSERT INTO @tab VALUES( '17530101 00:00:00.000' ) , ( GETDATE() ) , ( '99991231 23:59:59.997' ) SELECT *, DATALENGTH( colDATETIME ) AS lnColDateTime FROM @tab
DATETIME2
El rango es un poco más amplio y además la precisión de los decimales
es mayor, acepta un parámetro que define este ultimo dato que es de 0 a 7
digitos, el rango es de de 0001-01-01 00:00:00.0000000 a 9999-12-31
23:59:59.9999999 con un espacio en disco duro que varía de acuerdo a la
precisión establecida, si no establecemos una precisión, el default es 7 por lo
tanto ocupará 8 bytes:
Precision
|
Almacenamiento
|
0-2
|
6 bytes
|
3-4
|
7 bytes
|
5-7
|
8 bytes
|
Veamos un
ejemplo de lo que es posible almacenar cada tipo de dato y los bytes que
utiliza:
DECLARE @tab TABLE( colDATETIME2SinPrecision DATETIME2 ,colDATETIME20 DATETIME2(0) ,colDATETIME21 DATETIME2(1) ,colDATETIME22 DATETIME2(2) ,colDATETIME23 DATETIME2(3) ,colDATETIME24 DATETIME2(4) ,colDATETIME25 DATETIME2(5) ,colDATETIME26 DATETIME2(6) ,colDATETIME27 DATETIME2(7) ) INSERT INTO @tab VALUES( '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' ) , ( CAST( GETDATE() AS DATETIME2 ) , CAST( GETDATE() AS DATETIME2(0) ) , CAST( GETDATE() AS DATETIME2(1) ) , CAST( GETDATE() AS DATETIME2(2) ) , CAST( GETDATE() AS DATETIME2(3) ) , CAST( GETDATE() AS DATETIME2(4) ) , CAST( GETDATE() AS DATETIME2(5) ) , CAST( GETDATE() AS DATETIME2(6) ) , CAST( GETDATE() AS DATETIME2(7) ) ) , ( '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' ) SELECT * FROM @tab SELECT DATALENGTH( colDATETIME2SinPrecision ) AS lncolDATETIME2SinPrecision0 , DATALENGTH( colDATETIME20 ) AS lnColDATETIME20 , DATALENGTH( colDATETIME21 ) AS lnColDATETIME21 , DATALENGTH( colDATETIME22 ) AS lnColDATETIME22 , DATALENGTH( colDATETIME23 ) AS lnColDATETIME23 , DATALENGTH( colDATETIME24 ) AS lnColDATETIME24 , DATALENGTH( colDATETIME25 ) AS lnColDATETIME25 , DATALENGTH( colDATETIME26 ) AS lnColDATETIME26 , DATALENGTH( colDATETIME27 ) AS lnColDATETIME27 FROM @tab
DATETIMEOFFSET
Como aclaración, no explicaré el funcionamiento, solo la manera en que
podemos ahorrar espacio: de la misma manera que DATETIME2, usando una menor
precisión, solo que este tipo de datos ocupará un poco más de espacio porque también
almacena la zona horaria proporcionada, veamos el ejemplo y podremos darnos
cuenta de los bytes que almacena de acuerdo a la precisión, recuerden si no
utilizan el parámetro de precisión el default será 7 y por lo tanto estarán
ocupando el mayor espacio posible para el tipo de dato:
DECLARE @tab TABLE( DATETIMEOFFSETSinPrecision DATETIMEOFFSET ,DATETIMEOFFSET0 DATETIMEOFFSET(0) ,DATETIMEOFFSET1 DATETIMEOFFSET(1) ,DATETIMEOFFSET2 DATETIMEOFFSET(2) ,DATETIMEOFFSET3 DATETIMEOFFSET(3) ,DATETIMEOFFSET4 DATETIMEOFFSET(4) ,DATETIMEOFFSET5 DATETIMEOFFSET(5) ,DATETIMEOFFSET6 DATETIMEOFFSET(6) ,DATETIMEOFFSET7 DATETIMEOFFSET(7) ) INSERT INTO @tab VALUES( '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' ) , ( CAST( GETDATE() AS DATETIMEOFFSET ) , CAST( GETDATE() AS DATETIMEOFFSET(0) ) , CAST( GETDATE() AS DATETIMEOFFSET(1) ) , CAST( GETDATE() AS DATETIMEOFFSET(2) ) , CAST( GETDATE() AS DATETIMEOFFSET(3) ) , CAST( GETDATE() AS DATETIMEOFFSET(4) ) , CAST( GETDATE() AS DATETIMEOFFSET(5) ) , CAST( GETDATE() AS DATETIMEOFFSET(6) ) , CAST( GETDATE() AS DATETIMEOFFSET(7) ) ) , ( '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' ) SELECT * FROM @tab SELECT DATALENGTH( DATETIMEOFFSETSinPrecision ) AS lnDATETIMEOFFSETSinPrecision , DATALENGTH( DATETIMEOFFSET0 ) AS lnDATETIMEOFFSET0 , DATALENGTH( DATETIMEOFFSET1 ) AS lnDATETIMEOFFSET1 , DATALENGTH( DATETIMEOFFSET2 ) AS lnDATETIMEOFFSET2 , DATALENGTH( DATETIMEOFFSET3 ) AS lnDATETIMEOFFSET3 , DATALENGTH( DATETIMEOFFSET4 ) AS lnDATETIMEOFFSET4 , DATALENGTH( DATETIMEOFFSET5 ) AS lnDATETIMEOFFSET5 , DATALENGTH( DATETIMEOFFSET6 ) AS lnDATETIMEOFFSET6 , DATALENGTH( DATETIMEOFFSET7 ) AS lnDATETIMEOFFSET7 FROM @tab
TIME
De la misma manera, este tipo de dato usa un parámetro que es la precisión de hasta 7 decimales, si no utilizamos el parámetro, el default es 7 lo cual ocupa un espacio de 5 bytes, si no lo ocupan, en nuestro diseño de base de datos establezcamos la precisión a 0, veamos el ejemplo:
DECLARE @tab TABLE( TIMESinPrecision TIME ,TIME0 TIME(0) ,TIME1 TIME(1) ,TIME2 TIME(2) ,TIME3 TIME(3) ,TIME4 TIME(4) ,TIME5 TIME(5) ,TIME6 TIME(6) ,TIME7 TIME(7) ) INSERT INTO @tab VALUES( '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' , '00010101 00:00:00.1234567' ) ,( CAST( GETDATE() AS TIME ) , CAST( GETDATE() AS TIME(0) ) , CAST( GETDATE() AS TIME(1) ) , CAST( GETDATE() AS TIME(2) ) , CAST( GETDATE() AS TIME(3) ) , CAST( GETDATE() AS TIME(4) ) , CAST( GETDATE() AS TIME(5) ) , CAST( GETDATE() AS TIME(6) ) , CAST( GETDATE() AS TIME(7) ) ) , ( '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' , '99991231 23:59:59.9999999' ) SELECT * FROM @tab SELECT DATALENGTH( [TIMESinPrecision] ) AS lnTIMESinPrecision , DATALENGTH( TIME0 ) AS lnTIME0 , DATALENGTH( TIME1 ) AS lnTIME1 , DATALENGTH( TIME2 ) AS lnTIME2 , DATALENGTH( TIME3 ) AS lnTIME3 , DATALENGTH( TIME4 ) AS lnTIME4 , DATALENGTH( TIME5 ) AS lnTIME5 , DATALENGTH( TIME6 ) AS lnTIME6 , DATALENGTH( TIME7 ) AS lnTIME7 FROM @tab
A partir de las versiones más recientes de SQL SERVER ya tenemos
muchos más tipos de datos que podemos utilizar para ahorrar espacio no solo en
disco duro si no también la cantidad de información que se transmitirá por la
red, la cantidad de información que procesará nuestro servidor etcétera, por lo
que les recomiendo ampliamente que tengan especial cuidado al momento de elegir
dichos tipos de dato, sobre todo nunca elijan un tipo de dato que tenga una
precisión default, sabiendo que nunca utilizarán dicha precisión en la
información que pueden establecer a 0 para ocupar la menor cantidad de bytes.
Espero les sirva en su próximo diseño de tablas.
SALUDOS.
COMPARTE ESTA INFORMACION SI TE PARECIO INTERESANTE
0 comentarios:
Publicar un comentario