我有一张IP范围表以及拥有该IP范围的各自城市和国家/地区。 IP表示为bigint
(请参阅下面的等式,将IP转换为bigint
),我正在做一个选择以撤回使用网站的城市/国家/地区。
将IP转换为数字的公式为
Bigint = (octet1 * (2^24)) + (octet2 * (2^16)) + (octet3 * (2^8)) + Octet 4
我的选择如下所示。在任何一种情况下,当我有很多IP地址(200)要查找时,where子句可能会变得很长,结果需要几分钟才能返回。我确实将startipnum
和endipnum
编入索引作为聚簇索引。该表有625万行数据(IP范围和国家/地区)。有更好的方法来返回数据吗?
SELECT [startIpNum] ,[endIpNum],[country],[region],[city],[postal_code]
,[latitude],[longitude],[metroCode],[areacode]
FROM [GeoLocationView]
WHERE
(30072067 between startipNum and endipnum)
OR
(30072069 between startipNum and endipnum)
或
SELECT [startIpNum] ,[endIpNum],[country],[region],[city],[postal_code]
,[latitude],[longitude],[metroCode],[areacode]
FROM [GeoLocationView]
WHERE
(startipNum <= 30072067 and 30072067 <= endipnum) or
(startipNum <= 30072069 and 30072069 <= endipnum)
答案 0 :(得分:0)
您的群集会有所帮助。
我会选择x > ? order by x
where子句可以是来自单独表格的子选择,如下所示:
where key exists(select * from key_table)
但你必须维护这个key_table ......
当它尝试优化您的查询时 - 表查找更好地为RDMS引擎提供服务,而不是按键尾部
答案 1 :(得分:0)
可能有趣的是尝试将表变量(或临时表)与IP列表一起使用,并加入查找表
declare @ips table (ip bigint)
insert @ips (ip) values (30072067) -- etc...
SELECT <field list>
FROM [GeoLocationView]
inner join @ips as ips
on ((GeoLocationView.startipNum <= ip) and (GeoLocationView.endipnum) >= ip)
答案 2 :(得分:0)
当你必须匹配很多值时,OR子句通常比临时表上的JOIN慢。