【问题标题】:Utilize a function-based index while selecting additional columns在选择其他列时使用基于函数的索引
【发布时间】:2022-06-11 03:45:13
【问题描述】:

我有一个按预期工作的基于 Oracle 18c 函数的索引:

1.创建一个接受user-defined type对象的自定义函数,并以文本形式返回坐标列表:

create or replace function endpoint_list(shape in sde.st_geometry) return varchar2 
deterministic is
    coord_list varchar2(4000);
begin
    coord_list := 
      --sde.st_geometry functions are notoriously slow.  
      sde.st_geometry_operators.st_x_f(sde.st_geometry_operators.st_startpoint_f(sde.st_geometry_operators.st_geometryn_f(shape,1))) || ',' || 
            sde.st_geometry_operators.st_y_f(sde.st_geometry_operators.st_startpoint_f(sde.st_geometry_operators.st_geometryn_f(shape,1))) || ',' || 
                sde.st_geometry_operators.st_x_f(sde.st_geometry_operators.st_endpoint_f(  sde.st_geometry_operators.st_geometryn_f(shape,1))) || ',' ||
                    sde.st_geometry_operators.st_y_f(sde.st_geometry_operators.st_endpoint_f(  sde.st_geometry_operators.st_geometryn_f(shape,1)));
return coord_list; 
end;

2.在自定义函数上创建基于函数的索引(FBI):

create index atn_endpoint_list_idx on my_owner.active_transportation(my_owner.endpoint_list(shape));

3.在 SELECT 子句中运行使用 FBI 的查询:

select  
    endpoint_list(shape) as list
from
    active_transportation --15,000 rows
where
    endpoint_list(shape) is not null


----------------------------------------------------------------------------------------------
| Id  | Operation            | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                       |   727 |   299K|    50  (10)| 00:00:01 |
|*  1 |  INDEX FAST FULL SCAN| ATN_ENDPOINT_LIST_IDX |   727 |   299K|    50  (10)| 00:00:01 |
----------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("my_owner"."ENDPOINT_LIST"("SHAPE") IS NOT NULL)

FBI 按预期工作。当我选择 endpoint_list(shape) 作为列时,查询使用索引,将运行时间从 65 秒缩短到 0.09 秒。很好。


除了选择endpoint_list(shape)之外,我还想从表中选择其他列,比如OBJECTID列:

select  
    objectid,  --Note: OBJECTID has a index of it's own (unique).
    endpoint_list(shape) as list
from
    active_transportation
where
    endpoint_list(shape) is not null

-------------------------------------------------------------------------------------------
| Id  | Operation         | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                       |   727 |   299K|   181   (4)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| ACTIVE_TRANSPORTATION |   727 |   299K|   181   (4)| 00:00:01 |
-------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("my_owner"."ENDPOINT_LIST"("SHAPE") IS NOT NULL)

现在,FBI没有被使用。查询改为执行全表扫描,这不是我想要的。


问题:

如何在选择其他列时利用基于函数的索引?

【问题讨论】:

  • 当你添加不在索引中的列时,db必须在读取索引后读取表。并且在您的情况下,优化器认为它将返回所有行,数据库更容易读取表。尝试收集统计数据,看看它是否会在这两种情况下改变成本和估计行。
  • @gsalem 谢谢。你的评论很有帮助。我在使用复合索引的地方发布了一个答案。

标签: sql oracle indexing query-optimization oracle18c


【解决方案1】:

解决方案是将附加列 (OBJECTID) 添加到索引中 — 作为复合索引:

create index atn_endpoint_list_idx on
    my_owner.active_transportation(my_owner.endpoint_list(shape),OBJECTID);
--                                                                  ?

现在,FBI 正在被使用:

----------------------------------------------------------------------------------------------
| Id  | Operation            | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                       |   727 |   299K|    53  (10)| 00:00:01 |
|*  1 |  INDEX FAST FULL SCAN| ATN_ENDPOINT_LIST_IDX |   727 |   299K|    53  (10)| 00:00:01 |
----------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("my_owner"."ENDPOINT_LIST"("SHAPE") IS NOT NULL)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 2012-07-22
    • 1970-01-01
    • 2020-08-30
    相关资源
    最近更新 更多