问题来源
同事在面字节的时候遇到的。
我的理解
数据库表中,有一个表,是以url为主键来区分数据,但是url很长,如果根据url进行查找,比较耗时,所以需要根据特殊的手段进行优化。
问题答案
方案一
除了存储url字段,还需要新增一个字段,存储url的哈希值,查找时,根据url的哈希值进行查找。
- 可能存在的问题
会发生哈希碰撞,可以在查找出来之后,在内存中进行二次过滤,进行精确全url的匹配查找,使用url.equals(…)地方式进行精确匹配,过滤出自己想要的那一条或者几条数据。 - 如果url特别长,计算哈希值会消耗比较多的CPU资源。
方案二
-
方案
额外存储一个字段,url的前缀,存储url字段的前N位,具体可以根据url的特征来判断,比如可以存储前10位或者前20位,或者前30位。
这种方式会跟存储url的哈希值的方式一样,可能会发生碰撞,但是解决方案也是一样,在数据库中查找出几条数据之后,在内存中进行二次精确过滤。 -
可能存在的问题
有可能会出现url的前缀都很相似,从数据库中查找出的数据可能会很多,有可能会占用大量的内存。
方案三
-
方案
额外存储一个字段,url的中缀,存储url字段的N至M位,具体可以根据url的特征来判断,比如可以存储第10位至20位。
这种方式会跟存储url的哈希值的方式一样,可能会发生碰撞,但是解决方案也是一样,在数据库中查找出几条数据之后,在内存中进行二次精确过滤。 -
可能存在的问题
可能url的总长度只有15位,所以这种方案可以继续优化,优化为存url长度的三分之一长度开始,到四分之一的长度。
但是三分之一到四分之一可能会很长,所以可以继续优化为存储三分之一到四分之一,但是最长长度为10.
方案四
-方案
存储url的后缀,存储后10位,如果不足10位,则存储整个url。
- 方案优点
后缀一般不会发生太大的碰撞。 - 可能得缺点
但是也有可能会发生碰撞,具体要根据url的特点来决定。
最后的考虑
选择哪种方案,要根据url的特点来考虑。