J'ai besoin de stocker des entiers non signés de 128 bits dans MySQL et je me demandais quel est le meilleur type de données pour stocker de tels nombres.
En ce moment, j'utilise binary(16)
mais cela implique beaucoup de fonction de conversion pack(/huge number in hex .../)
.
Y a-t-il un meilleur type de données pour stocker un entier non signé de 128 bits?
Je ne sais pas quelle est la meilleure façon de le stocker - mais il y a au moins une meilleure option que d'utiliser une varchar(39)
(ou varchar(40)
si vous en aviez besoin de signature); Utilisez plutôt une decimal(39,0)
. à partir des docs MySQL :
Types à point fixe (valeur exacte)
Les types décimaux et numériques stockent des valeurs de données numériques exactes. Ces types sont utilisés lorsqu'il est important de préserver une précision exacte, par exemple avec des données monétaires. Dans MySQL, le numérique est mis en œuvre comme décimal, de sorte que les remarques suivantes sur la décimale s'appliquent également à numériques.
MySQL 5.1 stocke les valeurs décimales en format binaire. Avant MySQL 5.0.3, ils ont été stockés comme des chaînes. Voir la section 11.18, "Math de précision".
Dans une déclaration de colonne décimale, la précision et l'échelle peuvent être (et généralement) spécifiées; par exemple:
salary DECIMAL(5,2)
Dans cet exemple, 5 est la précision et 2 est la balance. La précision représente le nombre de chiffres significatifs stockés pour les valeurs et que l'échelle représente le nombre de chiffres pouvant être stockés après le point décimal.
SQL standard nécessite que la décimale (5,2) soit capable de stocker n'importe quelle valeur avec cinq chiffres et deux décimales, de sorte que les valeurs pouvant être stockées dans la plage de colonnes de salaire de -999,99 à 999,99.
Dans SQL standard, la syntaxe décimale (M) est équivalente à la décimale (m, 0). De même, la décimale de syntaxe est équivalente à la décimale (m, 0), où la mise en œuvre est autorisée à décider de la valeur de M. MySQL prend en charge ces deux formes variantes de syntaxe décimale. La valeur par défaut de M est 10.
Si l'échelle est de 0, les valeurs décimales ne contiennent aucun point décimal ou une partie fractionnée.
Le nombre maximum de chiffres de la décimale est de 65 ans, mais la plage réelle d'une colonne décimale donnée peut être limitée par la précision ou la balance pour une colonne donnée. Lorsqu'une telle colonne est attribuée une valeur avec plus de chiffres après le point décimal que celui autorisé par l'échelle spécifiée, la valeur est convertie en cette échelle. (Le comportement précis est spécifique au système d'exploitation, mais l'effet est généralement de la troncature du nombre de chiffres admissibles.)
Il est stocké emballé, donc ça prendra moins d'espace que le Varchar ( 18 octets, si je fais mes mathématiques à droite ), et j'espère que vous pourriez faire des maths sur Cela directement, mais je n'ai jamais essayé avec ce grand nombre de chiffres pour voir ce qui se passe.
Je me suis retrouvé poser à cette question et de tous les postes que j'ai lus n'a jamais trouvé de comparaisons de performance. Alors voici ma tentative.
J'ai créé les tables suivantes, peuplées avec 2 000 000 adresses IP aléatoires à partir de 100 réseaux aléatoires.
CREATE TABLE ipv6_address_binary (
id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
addr BINARY(16) NOT NULL UNIQUE
);
CREATE TABLE ipv6_address_twobigints (
id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
haddr BIGINT UNSIGNED NOT NULL,
laddr BIGINT UNSIGNED NOT NULL,
UNIQUE uidx (haddr, laddr)
);
CREATE TABLE ipv6_address_decimal (
id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
addr DECIMAL(39,0) NOT NULL UNIQUE
);
Ensuite, je sélectionne toutes les adresses IP pour chaque réseau et enregistrer le temps de réponse. Le temps de réponse moyen sur la table Twobigints est d'environ 1 seconde lors de la table binaire, il est d'environ un centième de seconde.
Voici les questions.
Noter:
X_ [haut/bas] est le plus/le moins significatif 64 bits de x
lorsque NetMask_LOW est 0 et que la condition est omise car elle donne toujours vrai. n'affecte pas beaucoup les performances.
SELECT COUNT(*) FROM ipv6_address_twobigints
WHERE haddr & NETMASK_HIGH = NETWORK_HIGH
AND laddr & NETMASK_LOW = NETWORK_LOW
SELECT COUNT(*) FROM ipv6_address_binary
WHERE addr >= NETWORK
AND addr <= BROADCAST
SELECT COUNT(*) FROM ipv6_address_decimal
WHERE addr >= NETWORK
AND addr <= BROADCAST
Temps de réponse moyens:
BINARY_InnoDB 0.0119529819489
BINARY_MyISAM 0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB 0.782350552082
BIGINT_MyISAM 1.07809265852
Je crois que la seule autre option est de le stocker dans un champ varchar(39)
.