Трудно сказать, не зная, как вы проиндексировали таблицу, но, вероятно, нужен комбинированный индекс для 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 :(
Проблема при индексации начала диапазона (для большинства СУБД), это то, что диапазон будет проходить от наименьшего элемента, и вы действительно заинтересованы в наибольшем элементе, поэтому даже этот индексный поиск станет операцией O(n)
.