最近改一个比较老的web系统,该系统是通过账号或者ip地址(白名单)验证限制访问权限的。
由于运营的时间比较长了,发现进入网站巨卡...
原因就是:之前的数据库(sqlserver)存储ip地址是用的字符串类型,而且ip段被分解成了单个的ip存储起来,这样导致了巨大的数据量,比如(192.168.0.1-192.168.0.100),这样分解后存储会产生100条数据,导致在验证用户的时候查询超慢。
解决方法:
1:将ip地址存储类型改为varbinary(4)类型(未考虑ipv6),因为ip地址正好可以转换成长度为4的十六进制字节数组。
varbinary对应c#类型为byte[],下面是string byte[]互转的简单方法:
/// <summary> /// IP转换字节 /// </summary> /// <param name="ip"></param> /// <returns></returns> public static byte[] ParseByte(string ip) { return System.Net.IPAddress.Parse(ip).GetAddressBytes(); }
/// <summary> /// 字节转换IP字符串(未检查是否合法) /// </summary> /// <param name="b"></param> /// <returns></returns> public static string ParseIp(byte[] b) { if (b == null || b.Length < 0) return ""; string ipstr = ""; foreach (var _b in b) { ipstr += _b.ToString() + "."; } return ipstr.TrimEnd('.'); }
如此将字符串ip转换后可以直接当参数传递给sql语句进行查询。
2:ip段不再分解,而是用起始ip和结束ip两个字段来存储。
字节类型可以直接用来比较:
select * from Ip where IpStart <= @ip and IpEnd >= @ip
这样问题就都解决了。