将存储IPv4 / 6地址的LONGTEXT记录转换为INT(10)UNSIGNED和BINARY(16)

时间:2018-05-09 19:47:14

标签: mysql

我的应用程序上有一个表,存储了数以万计的事件(例如用户登录时)并且数量正在增长。每个事件都记录IP地址,可以是IPv4 / 6。这不是优雅的设计,也不是存储记录或索引的有效方法。

IPv4应存储为headers: { 'X-CSRF-TOKEN': 'Token Here' // from meta ,IPv6应存储为INT(10) UNSIGNED(我是对的吗?)。我想创建两个新列,例如BINARY(16)ipv4并使用ipv6或IPv4 / 6地址填充它们。目前,所有IP地址都存储在名为NULL的列中,作为event_meta

可以这样做吗?

2 个答案:

答案 0 :(得分:0)

你质疑“......应该存储为......我是对的吗?”很难回答,但可能不是。此处的错误在问题本身中,特别是您没有指定存储这些值的要求。在某些情况下,打包的二进制表示(IPv4为8个八位字节,IPv8为16个)是最好的,在其他情况下,通常的文本表示更好。您拥有哪种情况取决于您(未知)的要求。

现在,关于这个特殊情况,这就是我作为一个理智的默认情况所做的事情:

  1. 将IPv4转换为IPv6。从IPv4到IPv6有一个明确的,可逆的映射,因此每个IPv4地址在IPv6数字空间中只有一个表示。

  2. 将IP地址格式化为文本。 RFC 4291定义了这种格式,请参阅维基百科页面作为开始。

  3. 您得到的是一个包含最多39个字符的单个列。这是人类可读的,用于诊断和维护任务。此外,它可以被有效地编入索引,如果这只是几千个条目的关注点。

答案 1 :(得分:0)

我在创建上述两列ipv4ipv6之后自己解决了这个问题,解决方案比Ulrich的方法更有效。

<强>查询:

UPDATE user_activity SET ipv4 = CASE WHEN event_meta LIKE "%.%" THEN INET_ATON(event_meta) ELSE NULL END, ipv6 = CASE WHEN event_meta LIKE "%:%" THEN INET6_ATON(event_meta) ELSE NULL END;

这需要1.93秒,或每秒约35,000行。我将LIKE运算符与通配符.:一起使用。对于其他读者来说,正则表达式匹配可能会比目前的69,000行快得多,但对于某些MySQL版本,这并不总是支持。