对范围进行快速 SQL 查询

发布于 2024-12-11 17:40:32 字数 1059 浏览 0 评论 0原文

我有一个 IP 范围表以及拥有该 IP 范围的各自城市和国家/地区。 IP 表示为 bigint(请参阅下面的公式将 IP 转换为 bigint),我正在执行一个选择来拉回正在使用网站的城市/国家。

将 IP 转换为数字的方程式是

Bigint = (octet1 * (2^24)) + (octet2 * (2^16)) + (octet3 * (2^8)) + Octet 4

我的选择如下所示。无论哪种情况,当我有很多 IP 地址 (200) 需要查找时,where 子句可能会变得很长,并且需要几分钟才能返回结果。我确实将 startipnumendipnum 索引为聚集索引。该表有 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)

I have a table of IP Ranges and their respective city and country that owns that IP Range. The IPs are represented as bigint (See equation below for turning IP into bigint) and I am doing a select to pull back what cities/countries that are using a website.

Equation for converting IP to number is

Bigint = (octet1 * (2^24)) + (octet2 * (2^16)) + (octet3 * (2^8)) + Octet 4

My selects are looking like the following below. In either case, when I have a lot of IP addresses (200) to look up, the where clause can get very long and the results take minutes to return. I do have the startipnum and endipnum indexed as a clustered index. The table has 6.25 million rows of data (IP ranges and countries in it). Is there a better way to return the data?

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)

Or

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

肩上的翅膀 2024-12-18 17:40:32

尝试使用带有 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)

Might be interesting to try using a table variable (or temp table) with the list of IPs, joined to your lookup table

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)
眼睛会笑 2024-12-18 17:40:32

当您必须匹配大量值时,OR 子句通常比临时表上的 JOIN 慢。

When you have to match a lot of values, an OR clause is often slower than a JOIN on a temporary table.

很酷又爱笑 2024-12-18 17:40:32

您的集群会有所帮助。

我会选择 x > ? order by x

where 子句可以是来自单独表的子查询,如下所示:

where key exists(select * from key_table)

但是您必须维护此 key_table ...

当它尝试优化您的查询时 - 表查找比尾部更好地为 RDMS 引擎服务钥匙数

Your cluster will help.

I would select x > ? order by x

the where clause could be a subselect from a separate table like this:

where key exists(select * from key_table)

but you have to maintain this key_table ...

When it tries to optimize your query - table lookups serve the RDMS engine better, than a tail of keys

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文