<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Storing IPv6 IPs in MySQL</title>
	<atom:link href="http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/</link>
	<description>Dave Koopman&#039;s Blog</description>
	<lastBuildDate>Mon, 30 Jan 2012 09:18:36 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
	<item>
		<title>By: rchandra</title>
		<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/comment-page-1/#comment-704</link>
		<dc:creator>rchandra</dc:creator>
		<pubDate>Mon, 21 Feb 2011 04:15:24 +0000</pubDate>
		<guid isPermaLink="false">#comment-704</guid>
		<description>Why do you folks insist on calling it &quot;an IP?&quot;  No, it is &quot;an address&quot; for starters...or if you want to abbreviate it, &quot;addr.&quot;  The most bizzarre thing I see above is &quot;IPv6 IPs&quot;...gee...how is that so different than &quot;IPv6 addr?&quot;

Anyhow...you are also confusing storing an address with storing a network specification.  A network specification is what has a bitmask length.  If, as you say, you&#039;re looking for specific hosts in a table, it&#039;s either there, or it&#039;s not; or it is between two values where you can find the minimum and maximum address values given an address and a bitmask, and query for (valu &gt;= min and valu &lt;=max).  In other words, you should be doing the masking BEFORE any query.

If a single integer data type isn&#039;t big enough, your best bet for lookup/indexing efficiency is probably normalization of all the addresses, filling in the missing zeroes from the compressed notations.

An index on the addresses will presumably help.  Yes, it probably makes sense also to store the bitmask lengths as well with each address, just that forming any aggregation of the two (such as a unique key or index on both the address and the mask) is rather unlikely methinks to be useful.  It also seems rather less than useful above to use bitmask length as a key.

Heck...I&#039;d think the best example of IPv6 storage and lookup efficiency could be found in the Linux or *BSD kernel sources where the routing tables are maintained and accessed.  In essence, that code must make decisions on which table entry to use thousands of times every second in some cases.</description>
		<content:encoded><![CDATA[<p>Why do you folks insist on calling it &#8220;an IP?&#8221;  No, it is &#8220;an address&#8221; for starters&#8230;or if you want to abbreviate it, &#8220;addr.&#8221;  The most bizzarre thing I see above is &#8220;IPv6 IPs&#8221;&#8230;gee&#8230;how is that so different than &#8220;IPv6 addr?&#8221;</p>
<p>Anyhow&#8230;you are also confusing storing an address with storing a network specification.  A network specification is what has a bitmask length.  If, as you say, you&#8217;re looking for specific hosts in a table, it&#8217;s either there, or it&#8217;s not; or it is between two values where you can find the minimum and maximum address values given an address and a bitmask, and query for (valu &gt;= min and valu &lt;=max).  In other words, you should be doing the masking BEFORE any query.</p>
<p>If a single integer data type isn&#039;t big enough, your best bet for lookup/indexing efficiency is probably normalization of all the addresses, filling in the missing zeroes from the compressed notations.</p>
<p>An index on the addresses will presumably help.  Yes, it probably makes sense also to store the bitmask lengths as well with each address, just that forming any aggregation of the two (such as a unique key or index on both the address and the mask) is rather unlikely methinks to be useful.  It also seems rather less than useful above to use bitmask length as a key.</p>
<p>Heck&#8230;I&#039;d think the best example of IPv6 storage and lookup efficiency could be found in the Linux or *BSD kernel sources where the routing tables are maintained and accessed.  In essence, that code must make decisions on which table entry to use thousands of times every second in some cases.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Claus</title>
		<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/comment-page-1/#comment-37</link>
		<dc:creator>Claus</dc:creator>
		<pubDate>Thu, 12 Feb 2009 14:18:21 +0000</pubDate>
		<guid isPermaLink="false">#comment-37</guid>
		<description>Of course a typo has ocurred:
POW(65534... must be changed to POW(65535...</description>
		<content:encoded><![CDATA[<p>Of course a typo has ocurred:<br />
POW(65534&#8230; must be changed to POW(65535&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Claus</title>
		<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/comment-page-1/#comment-36</link>
		<dc:creator>Claus</dc:creator>
		<pubDate>Wed, 11 Feb 2009 10:28:29 +0000</pubDate>
		<guid isPermaLink="false">#comment-36</guid>
		<description>What about

mysql&gt; SELECT CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,4) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,3) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,2) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,1) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,0) AS DECIMAL(39,0));
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +
CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +
CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +
CAST(CONV &#124;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124;                                                                                                                                                                                                                         340209681578175878893739963388222212325 &#124;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&gt; SELECT CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,4) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,3) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,2) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,1) AS DECIMAL(39,0)) +
    -&gt; CAST(CONV(&#039;fffe&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,0) AS DECIMAL(39,0));
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124; CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +
CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +
CAST(CONV(&#039;ffff&#039;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +
CAST(CONV &#124;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124;                                                                                                                                                                                                                         340209681578175878893739963388222212324 &#124;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)</description>
		<content:encoded><![CDATA[<p>What about</p>
<p>mysql&gt; SELECT CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,4) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,3) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,2) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,1) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,0) AS DECIMAL(39,0));<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +<br />
CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +<br />
CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +<br />
CAST(CONV |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
|                                                                                                                                                                                                                         340209681578175878893739963388222212325 |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
<p>mysql&gt; SELECT CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,4) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,3) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,2) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,1) AS DECIMAL(39,0)) +<br />
    -&gt; CAST(CONV(&#8216;fffe&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,0) AS DECIMAL(39,0));<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,7) AS DECIMAL(39,0)) +<br />
CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,6) AS DECIMAL(39,0)) +<br />
CAST(CONV(&#8216;ffff&#8217;,16,10) AS DECIMAL(39,0)) * CAST(POW(65534,5) AS DECIMAL(39,0)) +<br />
CAST(CONV |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
|                                                                                                                                                                                                                         340209681578175878893739963388222212324 |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: DaveK</title>
		<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/comment-page-1/#comment-24</link>
		<dc:creator>DaveK</dc:creator>
		<pubDate>Tue, 23 Sep 2008 04:34:58 +0000</pubDate>
		<guid isPermaLink="false">#comment-24</guid>
		<description>mysql&gt; show create table address;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124; Table   &#124; Create Table                                                                                                                                                                                &#124;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
&#124; address &#124; CREATE TABLE `address` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `ip` decimal(39,0) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 &#124;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql&gt; Insert into address set ip= CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 7) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 6) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 5) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 4) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 3) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 2) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 1) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 0);

Query OK, 1 row affected, 1 warning (0.07 sec)

mysql&gt; Insert into address set ip= CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 7) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 6) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 5) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 4) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 3) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 2) +
    -&gt; CONV(&#039;ffff&#039;, 16, 10) * POW(65535, 1) +
    -&gt;
    -&gt; CONV(&#039;fffe&#039;, 16, 10) * POW(65535, 0);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql&gt; select * from address;
+----+-----------------------------------------+
&#124; id &#124; ip                                      &#124;
+----+-----------------------------------------+
&#124; 10 &#124; 340246022585899900000000000000000000000 &#124;
&#124; 11 &#124; 340246022585899900000000000000000000000 &#124;
+----+-----------------------------------------+
2 rows in set (0.00 sec)

Question:
What&#039;s wrong with this picture?
Answer:
The calculated values are identical, but they are not from the same IP.  In fact the values inserted are not the correct decimal representation.  This is due to MySQL losing precision in the POW calculation.

This is why:

mysql&gt; select POW(65535, 7);
+--------------------+
&#124; POW(65535, 7)      &#124;
+--------------------+
&#124; 5.191742286784e+33 &#124;
+--------------------+
1 row in set (0.00 sec)

So, DECIMAL(39) will work great for storing, and even does good on math such as where ip &gt; value1 and ip &lt; value2.  Just have to do the IPv6 to decimal mathematics outside of MySQL.

If someone can show a reliable method for converting an IPv6 IP to a decimal value using MySQL, that would be awesome!</description>
		<content:encoded><![CDATA[<p>mysql> show create table address;<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+<br />
| Table   | Create Table                                                                                                                                                                                |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+<br />
| address | CREATE TABLE `address` (<br />
  `id` int(10) unsigned NOT NULL auto_increment,<br />
  `ip` decimal(39,0) default NULL,<br />
  PRIMARY KEY  (`id`)<br />
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 |<br />
+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+<br />
1 row in set (0.00 sec)</p>
<p>mysql> Insert into address set ip= CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 7) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 6) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 5) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 4) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 3) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 2) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 1) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 0);</p>
<p>Query OK, 1 row affected, 1 warning (0.07 sec)</p>
<p>mysql> Insert into address set ip= CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 7) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 6) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 5) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 4) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 3) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 2) +<br />
    -> CONV(&#8216;ffff&#8217;, 16, 10) * POW(65535, 1) +<br />
    -><br />
    -> CONV(&#8216;fffe&#8217;, 16, 10) * POW(65535, 0);<br />
Query OK, 1 row affected, 1 warning (0.00 sec)</p>
<p>mysql> select * from address;<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| id | ip                                      |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| 10 | 340246022585899900000000000000000000000 |<br />
| 11 | 340246022585899900000000000000000000000 |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
2 rows in set (0.00 sec)</p>
<p>Question:<br />
What&#8217;s wrong with this picture?<br />
Answer:<br />
The calculated values are identical, but they are not from the same IP.  In fact the values inserted are not the correct decimal representation.  This is due to MySQL losing precision in the POW calculation.</p>
<p>This is why:</p>
<p>mysql> select POW(65535, 7);<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| POW(65535, 7)      |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| 5.191742286784e+33 |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
<p>So, DECIMAL(39) will work great for storing, and even does good on math such as where ip > value1 and ip < value2.  Just have to do the IPv6 to decimal mathematics outside of MySQL.</p>
<p>If someone can show a reliable method for converting an IPv6 IP to a decimal value using MySQL, that would be awesome!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom</title>
		<link>http://www.koopman.me/2008/04/storing-ipv6-ips-in-mysql/comment-page-1/#comment-21</link>
		<dc:creator>Tom</dc:creator>
		<pubDate>Wed, 13 Aug 2008 03:21:29 +0000</pubDate>
		<guid isPermaLink="false">#comment-21</guid>
		<description>Yes, definitely a single query with 128 &quot;=&quot; conditions will run a lot slow, than just 8 conditions with the ipsmallint method.  Index lookups are fast, but they still add up.

There is another method though:  use DECIMAL and store the entire IP as an integer.  IPv6 IPs can range from 0 to 340282366920938463463374607431768211455 when expressed as an integer.  You can store that in a DECIMAL(39) column.  Mask lookups will still involve using 128 lookups (or 8 if you want to limit yourself).  However, the advantage of DECIMAL(39) is that you can do range lookups.</description>
		<content:encoded><![CDATA[<p>Yes, definitely a single query with 128 &#8220;=&#8221; conditions will run a lot slow, than just 8 conditions with the ipsmallint method.  Index lookups are fast, but they still add up.</p>
<p>There is another method though:  use DECIMAL and store the entire IP as an integer.  IPv6 IPs can range from 0 to 340282366920938463463374607431768211455 when expressed as an integer.  You can store that in a DECIMAL(39) column.  Mask lookups will still involve using 128 lookups (or 8 if you want to limit yourself).  However, the advantage of DECIMAL(39) is that you can do range lookups.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

