通过单点有效检索重叠的IP范围记录

RC.*_*RC. 5 sql database oracle database-design

我有一个包含数百万个IP范围记录(分别为start_num,end_num)的表,我需要通过单个IP地址进行查询,以便返回与该点重叠的所有范围.查询基本上是:

SELECT start_num
       , end_num
       , other_data_col 
FROM ip_ranges 
WHERE :query_ip BETWEEN start_num and end_num;
Run Code Online (Sandbox Code Playgroud)

该表在start_num上有8个范围分区,并且在(start_num,end_num)上有一个本地复合索引.称之为UNQ_RANGE_IDX.已经在表和索引上收集了统计数据.

该查询按预期对UNQ_RANGE_IDX索引执行索引范围扫描,并且在某些情况下执行得非常好.它表现良好的情况是在IP地址空间的底部(即4.4.10.20之类),并且在高端时性能很差.(即200.2.2.2)我确定问题在于,在较低端,优化器可以修剪包含适用范围的分区之上的所有分区,因为start_num上的范围分区提供了必要的信息.修剪.查询IP频谱的最高端时,它无法修剪较低的分区,因此会产生读取其他索引分区的I/O. 这可以在跟踪执行时通过CR_BUFFER_GETS的数量来验证.

实际上,满足查询的范围将不在任何分区中,而是query_ip所在的范围或紧邻其下方或上方的范围,因为范围大小不会大于A类,并且每个分区覆盖许多A每个班级.我可以通过在where子句中指定它来使Oracle使用该信息,但有没有办法通过统计信息,直方图或自定义/域索引将此类信息传达给Oracle?在搜索涵盖特定日期的日期范围时,似乎会出现这种问题的共同解决方案/方法.

我正在寻找使用Oracle及其功能来解决此问题的解决方案,但其他解决方案类型也受到赞赏.我已经想到了Oracle范围之外的一些方法可以工作,但我希望有更好的方法来建立索引,统计信息收集或分区.

请求的信息:

CREATE TABLE IP_RANGES (
    START_NUM NUMBER NOT NULL, 
    END_NUM   NUMBER NOT NULL,
    OTHER     NUMBER NOT NULL,
    CONSTRAINT START_LTE_END CHECK (START_NUM <= END_NUM)
)
PARTITION BY RANGE(START_NUM)
(
    PARTITION part1 VALUES LESS THAN(1090519040) TABLESPACE USERS,
    PARTITION part2 VALUES LESS THAN(1207959552) TABLESPACE USERS
    ....<snip>....
    PARTITION part8 VALUES LESS THAN(MAXVALUE) TABLESPACE USERS
);

CREATE UNIQUE INDEX IP_RANGES_IDX ON IP_RANGES(START_NUM, END_NUM, OTHER) LOCAL NOLOGGING;

ALTER TABLE IP_RANGES ADD CONSTRAINT PK_IP_RANGE 
PRIMARY KEY(START_NUM, END_NUM, OTHER) USING INDEX IP_RANGES_IDX;
Run Code Online (Sandbox Code Playgroud)

为范围分区选择的截止值没有什么特别之处.它们只是一个类地址,其中每个分区的范围数等于大约1M条记录.

Gar*_*ers 1

我建议你把你的800万行表变成一个更大的表。谷歌的IP(目前对我来说)是

“66.102.011.104”

您将一条记录存储为“66.102.011”及其所属的相应范围。事实上,您为每个“aaa.bbb.ccc”至少存储一条记录。您最终可能会得到一张五倍大的表,但每次只需几个逻辑 IO,您就可以精确定位相关记录,而不是进行数百/数千个分区扫描。

我怀疑您拥有的任何数据无论如何都会有点过时(因为世界各地的各个机构发布/重新发布范围),因此每天/每周对该表进行重新调整应该不是一个大问题。