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条记录.
我建议你把你的800万行表变成一个更大的表。谷歌的IP(目前对我来说)是
“66.102.011.104”
您将一条记录存储为“66.102.011”及其所属的相应范围。事实上,您为每个“aaa.bbb.ccc”至少存储一条记录。您最终可能会得到一张五倍大的表,但每次只需几个逻辑 IO,您就可以精确定位相关记录,而不是进行数百/数千个分区扫描。
我怀疑您拥有的任何数据无论如何都会有点过时(因为世界各地的各个机构发布/重新发布范围),因此每天/每周对该表进行重新调整应该不是一个大问题。
| 归档时间: |
|
| 查看次数: |
1380 次 |
| 最近记录: |