You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle 18c如何在SELECT列表中使用基于函数的空间索引

问题背景

我有一张存储1000行数据的Oracle 18c表,表名为LINES,表结构与测试数据如下:

create table lines (shape sdo_geometry);
    insert into lines (shape) values (sdo_geometry(2002, 26917, null, sdo_elem_info_array(1, 2, 1), sdo_ordinate_array(574360, 4767080, 574200, 4766980)));
    insert into lines (shape) values (sdo_geometry(2002, 26917, null, sdo_elem_info_array(1, 2, 1), sdo_ordinate_array(573650, 4769050, 573580, 4768870)));
    insert into lines (shape) values (sdo_geometry(2002, 26917, null, sdo_elem_info_array(1, 2, 1), sdo_ordinate_array(574290, 4767090, 574200, 4767070)));
    insert into lines (shape) values (sdo_geometry(2002, 26917, null, sdo_elem_info_array(1, 2, 1), sdo_ordinate_array(571430, 4768160, 571260, 4768040)));
    ...

出于测试目的,我创建了一个故意设置为低执行效率的函数slow_function:该函数接收SDO_GEOMETRY类型的线要素作为入参,返回SDO_GEOMETRY类型的点要素,函数定义如下:

create or replace function slow_function(shape in sdo_geometry) return sdo_geometry  
deterministic is
begin
    return 
    -- 为测试故意降低函数执行效率:无意义地反复将SDO_GEOMETRY与JSON格式互转多次
    sdo_util.from_json(sdo_util.to_json(sdo_util.from_json(sdo_util.to_json(sdo_util.from_json(sdo_util.to_json(sdo_util.from_json(sdo_util.to_json(sdo_util.from_json(sdo_util.to_json(
        sdo_lrs.geom_segment_start_pt(shape)
    ))))))))));
end;

我希望创建基于函数的空间索引,通过预计算慢函数的返回结果,避免查询时重复执行耗时计算。


已执行的操作步骤
  • 在USER_SDO_GEOM_METADATA视图中添加元数据条目:
insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
  'lines', 
  'infrastr.slow_function(shape)',
  --  🡅 注意:此处需指定函数的所有者
  sdo_dim_array (
    sdo_dim_element('X',  567471.222,  575329.362, 0.5),  -- 自测备注:此处坐标范围配置有误
    sdo_dim_element('Y', 4757654.961, 4769799.360, 0.5)
  ),
 26917
);
commit;
  • 创建基于函数的空间索引:
create index lines_idx on lines (slow_function(shape)) indextype is mdsys.spatial_index_v2;

遇到的问题

当我在查询的SELECT列表中调用上述函数时,创建的空间索引并未被调用,执行计划显示数据库进行全表扫描,导致查询全量行时速度依然很慢。

注:之所以查询全量行,是因为制图软件的常规工作模式需要一次性加载地图中全部(或大部分)点要素完成渲染。

执行计划如下:

explain plan for

select
    slow_function(shape)
from
    lines

select * from table(dbms_xplan.display);

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     1 |    34 |     7   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| LINES |     1 |    34 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------

该问题同样出现在制图软件端:我使用的ArcGIS Desktop 10.7.1加载数据时也未调用该索引,直观表现为地图中点要素绘制速度很慢。


已尝试的无效方案
  • 创建视图,除注册空间索引外,同时在USER_SDO_GEOM_METADATA中注册该视图,再在地图中加载视图,但制图软件依然无法使用该索引;
  • 在视图定义中添加SQL提示强制使用索引,但提示未被执行器采纳,视图定义代码如下:
create or replace view lines_vw as (
select
    /*+ INDEX (lines lines_idx) */
    cast(rownum as number(38,0)) as objectid, -- 制图软件需要唯一ID列
    slow_function(shape) as shape
from
    lines  
where
    slow_function(shape) is not null
)  

咨询问题

如何才能在查询的SELECT列表中正常调用已创建的基于函数的空间索引,避免全表扫描重复执行耗时函数?


内容的提问来源于stack exchange,提问作者User1974

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:21:55