Je vais créer une table avec deux champs - ID
comme BIGINT
et IPAddress
comme varchar(45)
ou varbinary(16)
. L'idée est de stocker toutes les adresses IP uniques et d'utiliser une référence à la ID
place de la réelle IP address
dans d'autres tableaux.
Généralement, je vais créer une procédure stockée qui renvoie le ID
pour donné IP address
ou (si l'adresse n'a pas été trouvée) insérer l'adresse et renvoyer le généré ID
.
Je m'attends à avoir de nombreux enregistrements (je ne peux pas dire exactement combien), mais j'ai besoin que la procédure stockée ci-dessus soit exécutée le plus rapidement possible. Donc, je me demande comment stocker l'adresse IP réelle - au format texte ou octets. Qu'est-ce qui va être mieux?
J'ai déjà écrit des SQL CLR
fonctions pour transformer les octets d'adresse IP en chaîne et inversement, donc la transformation n'est pas un problème (travailler avec les deux IPv4
et IPv6
).
Je suppose que je dois créer un index pour optimiser la recherche, mais je ne suis pas sûr de devoir inclure le IP address
champ à l'index clusterisé, ou de créer un index séparé et avec quel type la recherche sera plus rapide?
IPv4
je suppose que je convertirais l'adresseINT
et utiliserais le champ comme clé d'index. Mais carIPv6
j'ai besoin d'utiliser deuxBIGINT
champs et je préfère stocker la valeur dans un champ - me semble plus naturel.Réponses:
Puisque "texte" fait référence ici
VARCHAR(45)
et "octets" fait référenceVARBINARY(16)
, je dirais: ni l'un ni l'autre .Compte tenu des informations suivantes (tirées d'un article de Wikipédia sur IPv6 ):
Je commencerais par utiliser 8
VARBINARY(2)
champs pour représenter les 8 groupes. Les champs des groupes 5 à 8 doivent êtreNULL
tels qu'ils ne seront utilisés que pour les adresses IPv6. Les champs des groupes 1 à 4 doivent êtreNOT NULL
tels qu'ils seront utilisés pour les adresses IPv4 et IPv6.En gardant chaque groupe indépendant (au lieu de les combiner dans un
VARCHAR(45)
ou unVARBINARY(16)
ou même deuxBIGINT
domaines), vous obtenez deux avantages principaux:IF
/IIF
/CASE
pour faciliter cela.ROW COMPRESSION
ouPAGE COMPRESSION
. Étant donné que les deux types de COMPRESSION permettront des champs qui doivent0x00
prendre 0 octets, tous ces groupes de zéros ne vous coûteront plus rien. D'un autre côté, si vous stockez l'exemple d'adresse ci-dessus (dans la citation de Wikipedia), alors les 3 ensembles de tous les zéros au milieu prendraient leur pleine quantité d'espace (à moins que vous ne le fassiez et que vous alliezVARCHAR(45)
avec la notation réduite , mais cela pourrait ne pas fonctionner correctement pour l'indexation et nécessiterait une analyse spéciale pour le reconstruire au format complet, supposons donc que ce n'est pas une option ;-).SI vous avez besoin de capturer le réseau, créez un
TINYINT
champ pour celui appelé, euh,[Network]
:-)Pour plus d'informations sur la valeur du réseau, voici quelques informations d'un autre article Wikipedia sur l'adresse IPv6 :
Pour l'indexation, je dirais créer un index non clusterisé sur les 8 champs Groupe, et éventuellement le champ Réseau si vous décidez de l'inclure.
Le résultat final devrait ressembler à ceci:
Remarques:
BIGINT
pour le champ ID, mais vous attendez-vous vraiment à capturer plus de 4 294 967 295 valeurs uniques? Si c'est le cas, changez simplement le champ en BIGINT et vous pouvez même changer la valeur de départ en 0. Mais sinon, vous feriez mieux d'utiliser INT et de commencer avec la valeur minimale afin de pouvoir utiliser toute la plage de ce type de données .SELECT *
renvoie les champs dans l'ordre attendu. Mais l'indice les fait monter , de 1 à 8, car c'est ainsi qu'ils sont remplis.Un exemple (inachevé) d'une colonne calculée pour représenter les valeurs sous forme de texte est:
Tester:
Résultat:
la source
VARDECIMAL
terminée,VARBINARY
car elleDATA_COMPRESSION
n'est pas disponible?BINARY(16)
;-). Pouvez-vous me donner un exemple avec une plage de début / fin et au moins deux lignes que vous récupérez, une valide et au moins une invalide? Il se peut que VARbinary raccourcisse certaines valeurs.Plus petit sera toujours plus rapide. Avec des valeurs plus petites, vous pouvez en insérer plus sur une seule page, donc moins d'E / S, des arbres B potentiellement moins profonds, etc.
Toutes autres choses (surcharge de traduction, lisibilité, compatibilité, charge CPU, sargabilité d'index, etc.) étant égales, bien sûr.
la source