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
相关产品推荐
相关产品推荐

