我的应用程序上有一个表,存储了数以万计的事件(例如用户登录时)并且数量正在增长。每个事件都记录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
。
可以这样做吗?
答案 0 :(得分:0)
你质疑“......应该存储为......我是对的吗?”很难回答,但可能不是。此处的错误在问题本身中,特别是您没有指定存储这些值的要求。在某些情况下,打包的二进制表示(IPv4为8个八位字节,IPv8为16个)是最好的,在其他情况下,通常的文本表示更好。您拥有哪种情况取决于您(未知)的要求。
现在,关于这个特殊情况,这就是我作为一个理智的默认情况所做的事情:
将IPv4转换为IPv6。从IPv4到IPv6有一个明确的,可逆的映射,因此每个IPv4地址在IPv6数字空间中只有一个表示。
将IP地址格式化为文本。 RFC 4291定义了这种格式,请参阅维基百科页面作为开始。
您得到的是一个包含最多39个字符的单个列。这是人类可读的,用于诊断和维护任务。此外,它可以被有效地编入索引,如果这只是几千个条目的关注点。
答案 1 :(得分:0)
我在创建上述两列ipv4
和ipv6
之后自己解决了这个问题,解决方案比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版本,这并不总是支持。