[erlang-questions] Efficient way to select a range of data between 2 values?

Paul Mineiro paul-trapexit@REDACTED
Mon Aug 31 19:00:13 CEST 2009


On Mon, 31 Aug 2009, Paul Mineiro wrote:

> >    	MatchHead = #ip_address_map{range_from='$1', range_to='$2',
> > country_code='$3'},
> >    	Guard = [{'=<', '$1', IP}, {'>=', '$2', IP}],
> >    	Result = '$3',
> > 	ets:select(ip, [{MatchHead, Guard, [Result]}], 1).

...

> Since you say {'=<','$1',IP} you need to do an initial lookup of the lower
> bound to get the equality, but if the problem is {'<', '$1', IP} you don't
> even need to do that since the Key argument to ets:next/2 in an
> ordered_set table need not be a member of the table.

Whoops ... used the wrong guard there in the text.  Replace {'=<','$1',IP
} with {'>=','$2',IP }, and {'<','$1',IP } with {'>','$2',IP }.

Basically, just remember to do a ets:lookup (ip, LOWER_BOUND) to get
records that exactly match the lower bound, and otherwise do
ets:next (ip, Key) initially with Key = LOWER_BOUND and repeat until the
Key1 returned by ets:next/2 exceeds UPPER_BOUND.

Also do timing tests, because for this approach to make sense, the number
of records iterated over has to be small enough, because there's alot of
overhead in the repeated ets:next/2 calls.

-- p

p.z. you could always try tcerl, which optimizes this kind of select.
however the constant factors are much worse than ets.  Since your table
size is so small (100K entries), I'm thinking you should look into
in-memory based solutions.


More information about the erlang-questions mailing list