检查ipv6是否在范围内
Check if ipv6 is inside range
我有 maxmind 的 ipv6 数据。这是我当前的 table(带有示例数据):
+---------------+------------+
| network | geoname_id |
+---------------+------------+
| 2001:208::/32 | 123 |
| 2001:218::/32 | 4312 |
+---------------+------------+
使用 their converter,我可以创建 network_start_ip
和 network_last_ip
列:
+------------------+----------------------------------------+------------+
| network_start_ip | network_last_ip | geoname_id |
+------------------+----------------------------------------+------------+
| 2001:200:: | 2001:200:ffff:ffff:ffff:ffff:ffff:ffff | 123 |
| 2001:208:: | 2001:208:ffff:ffff:ffff:ffff:ffff:ffff | 4312 |
+------------------+----------------------------------------+------------+
我期待这样的事情会起作用(即使它可能比其他方法慢):
SELECT b.geoname_id FROM blocks b
WHERE HEX(INET6_ATON('2001:201:ffff:ffff:ffff:ffff:ffff:ffff')) BETWEEN HEX(b.network_start_ip) AND HEX(b.network_last_ip)
那么,我错过了什么?另外,存储 ipv6 地址(范围)的最佳方法是什么
谢谢
我是这样操作的:
- 创建了另一个具有相同列的 table,但是
network_start_ip
和 network_last_ip
是 VARBINARY(16)
- 使用以下语句填充 table:
INSERT INTO blocks
SELECT INET6_ATON(b2.network_start_ip), INET6_ATON(b2.network_last_ip), b2.geoname_id FROM blocks_copy b2;
- 然后,要检查 IPv6 地址是否在范围内,我只需要 运行 这个查询:
SELECT geoname_id FROM blocks b
WHERE INET6_ATON('2a01:4ff:ffff:ffff::ffff') BETWEEN b.network_start_ip AND b.network_last_ip
原来的 HEX(...)
是不必要的,正如您在自我回答中所观察到的那样。也就是说 BINARY(16)
很高兴能够正确比较 IPv6 值。
如果 table 中有无数行,您会发现查询很慢。这是因为没有索引可以始终如一地帮助优化器。可以进行快速查询,但它涉及删除 last_ip 列并用任何缺失的范围填充 table 。我用代码讨论这个,here.
我有 maxmind 的 ipv6 数据。这是我当前的 table(带有示例数据):
+---------------+------------+
| network | geoname_id |
+---------------+------------+
| 2001:208::/32 | 123 |
| 2001:218::/32 | 4312 |
+---------------+------------+
使用 their converter,我可以创建 network_start_ip
和 network_last_ip
列:
+------------------+----------------------------------------+------------+
| network_start_ip | network_last_ip | geoname_id |
+------------------+----------------------------------------+------------+
| 2001:200:: | 2001:200:ffff:ffff:ffff:ffff:ffff:ffff | 123 |
| 2001:208:: | 2001:208:ffff:ffff:ffff:ffff:ffff:ffff | 4312 |
+------------------+----------------------------------------+------------+
我期待这样的事情会起作用(即使它可能比其他方法慢):
SELECT b.geoname_id FROM blocks b
WHERE HEX(INET6_ATON('2001:201:ffff:ffff:ffff:ffff:ffff:ffff')) BETWEEN HEX(b.network_start_ip) AND HEX(b.network_last_ip)
那么,我错过了什么?另外,存储 ipv6 地址(范围)的最佳方法是什么
谢谢
我是这样操作的:
- 创建了另一个具有相同列的 table,但是
network_start_ip
和network_last_ip
是VARBINARY(16)
- 使用以下语句填充 table:
INSERT INTO blocks SELECT INET6_ATON(b2.network_start_ip), INET6_ATON(b2.network_last_ip), b2.geoname_id FROM blocks_copy b2;
- 然后,要检查 IPv6 地址是否在范围内,我只需要 运行 这个查询:
SELECT geoname_id FROM blocks b WHERE INET6_ATON('2a01:4ff:ffff:ffff::ffff') BETWEEN b.network_start_ip AND b.network_last_ip
原来的 HEX(...)
是不必要的,正如您在自我回答中所观察到的那样。也就是说 BINARY(16)
很高兴能够正确比较 IPv6 值。
如果 table 中有无数行,您会发现查询很慢。这是因为没有索引可以始终如一地帮助优化器。可以进行快速查询,但它涉及删除 last_ip 列并用任何缺失的范围填充 table 。我用代码讨论这个,here.