我有一张带ID,startIPNum和endIPNum的桌子。startIPNum和endIPNum已转换为长数字,而不是IP字符串。
以下查询有效,大约需要3000到3200毫秒
List<GeoIP> oneResult = new LinkedList(getHibernateTemplate().find(
"from GeoIP where "+ipNum+" >= startIpNum and "+ipNum+" <= endIpNum"));
此查询有效,大约需要3000到4700毫秒
List<GeoIP> oneResult = new LinkedList(getHibernateTemplate().find(
"from GeoIP where "+ipNum+" between startIpNum and endIpNum"));
问题是:有没有一种方法可以优化这个查找,从而节省很多时间?这张桌子有超过350万张唱片。
最佳答案
如果不知道如何为表编制索引,很难说,但可能需要对startIpNum
和endIpNum
进行组合索引:
CREATE INDEX range_idx ON geoip (endIPNum, startIPNum);
您可能还必须更改代码,这取决于查询优化器的智能程度。我做了一个类似的查找功能,其中组合索引不起作用,所以我只索引了范围结束,并做了如下操作:
candidateRanges = query("from geoip where range_end >= $ip order by range_end")
if candidateRanges.size > 0 and candidateRanges[0].range_start <= ip:
# We found a matching record, do something with it
else:
# No match :(
如果对range start进行索引(对于大多数dbms),问题是该范围将从最小的元素遍历,而您实际上对最大的元素感兴趣,因此即使是这个索引搜索也将成为一个
O(n)
操作。关于java - 使用Hibernate的Performance Optimization在startIPNum和endIPNum范围内查找IP号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4106719/