Voy a crear una tabla con dos campos: ID
como BIGINT
y IPAddress
como varchar(45)
o varbinary(16)
. La idea es almacenar todas las direcciones IP únicas y utilizar una referencia en ID
lugar de la real IP address
en otras tablas.
En general, voy a crear un procedimiento almacenado que devuelve el ID
dado IP address
o (si no se encontró la dirección) insertar la dirección y devolver la generada ID
.
Espero tener muchos registros (no puedo decir exactamente cuántos), pero necesito que el procedimiento almacenado anterior se ejecute lo más rápido posible. Entonces, me pregunto cómo almacenar la dirección IP real, en formato de texto o bytes. ¿Cuál va a ser mejor?
Ya he escrito SQL CLR
funciones para transformar los bytes de la dirección IP en cadena y viceversa, por lo que la transformación no es un problema (trabajar con ambos IPv4
y IPv6
).
Supongo que necesito crear un índice para optimizar la búsqueda, pero no estoy seguro de si debería incluir el IP address
campo en el índice agrupado, o crear un índice separado y con qué tipo la búsqueda será más rápida.
IPv4
, supongo que convertiría la direcciónINT
y usaría el campo como clave de índice. Pero porqueIPv6
necesito usar dosBIGINT
campos y prefiero almacenar el valor en un campo, me parece más natural.Respuestas:
Como "texto" aquí se refiere
VARCHAR(45)
y "bytes" se refiereVARBINARY(16)
, yo diría: ninguno .Dada la siguiente información (del artículo de Wikipedia sobre IPv6 ):
Comenzaría usando 8
VARBINARY(2)
campos para representar los 8 grupos. Los campos para los Grupos 5 - 8 deben serNULL
ya que solo se usarán para direcciones IPv6. Los campos para los Grupos 1 a 4 deben serNOT NULL
como se usarán para las direcciones IPv4 e IPv6.Al mantener a cada grupo independiente (en lugar de combinarlos en uno
VARCHAR(45)
o unoVARBINARY(16)
o incluso dosBIGINT
campos), obtiene dos beneficios principales:IF
/ simples para facilitar esto.IIF
CASE
ROW COMPRESSION
oPAGE COMPRESSION
. Dado que ambos tipos de COMPRESIÓN permitirán que los campos0x00
ocupen 0 bytes, todos esos grupos de ceros ahora no le costarán nada. Por otro lado, si almacenó la dirección de ejemplo de arriba (en la cita de Wikipedia), entonces los 3 conjuntos de todos los ceros en el medio ocuparían su cantidad total de espacio (a menos que lo hicieraVARCHAR(45)
y fuera con la notación reducida , pero eso podría no funcionar bien para la indexación y requeriría un análisis especial para reconstruirlo al formato completo, así que supongamos que no es una opción ;-).SI necesita capturar la red, cree un
TINYINT
campo para eso llamado, um,[Network]
:-)Para obtener más información sobre el valor de la red, aquí hay información de otro artículo de Wikipedia sobre la dirección IPv6 :
Para la indexación, yo diría que cree un índice no agrupado en los 8 campos de grupo, y posiblemente el campo de red si decide incluir eso.
El resultado final debería ser algo como lo siguiente:
Notas:
BIGINT
para el campo ID, pero ¿realmente espera capturar más de 4,294,967,295 valores únicos? Si es así, simplemente cambie el campo para que sea GRANDE e incluso puede cambiar el valor de inicialización a 0. Pero de lo contrario, será mejor que use INT y comience con el valor mínimo para que pueda usar todo el rango de ese tipo de datos .SELECT *
se devuelvan los campos en el orden esperado. Pero el índice los hace subir , de 1 a 8, ya que así es como se completan.Un ejemplo (sin terminar) de una columna calculada para representar los valores en forma de texto es:
Prueba:
Resultado:
fuente
VARDECIMAL
sobreVARBINARY
yaDATA_COMPRESSION
no está disponible?BINARY(16)
;-). ¿Me puede dar un ejemplo con un rango inicial / final y al menos dos filas que recupere, una válida y al menos una inválida? Puede ser que VARbinary acorte algunos valores.Más pequeño siempre será más rápido. Con valores más pequeños, puede colocar más de ellos en una sola página, por lo tanto, menos IO, B-Trees potencialmente menos profundos, etc.
Todas las demás cosas (sobrecarga de traducción, legibilidad, compatibilidad, carga de CPU, índice de sargabilidad, etc.) son iguales, por supuesto.
fuente