问题描述
我有一个带有状态标志的订单表,显示该订单是否已完成。表中的大多数订单已完成: 可能只有5% ish的表是不完整的。
我知道我可以通过使用基于函数的索引来构建部分索引,该索引根据状态标志的值返回订单id或null。这样,索引中只存储不完整的订单。这一切都很好。
我的问题是,如果我需要表中的许多其他列,并且只希望索引扫描以避免计划中的索引ROWID访问表,那么执行此操作的最佳方法是什么。假设我也想要客户id和产品id。这些值永远不会为空,所以如果我将它们添加到索引中,这意味着我不会以部分索引结束,因为空值将只为初始函数列添加,因为其他2列将始终具有值。所以我看到了基本的方法,不确定哪种方法更好。
1.我构建一个由一串函数组成的索引,所有函数都根据状态字段的值返回所需的值。
2.我保留第一列基于查看状态的函数,但我只构建了一个索引,该索引不用作谓词或过滤器的一部分,但实际上返回了一个较大的预计算json对象,该对象从索引中的第二个函数返回,并根据该函数中所有必需的值作为参数返回一个json对象,以及用于确定该函数是否返回null或json对象的状态标志。
或者也许有一种更好的方法来构建带有额外foelds的部分索引?
我知道我可以通过使用基于函数的索引来构建部分索引,该索引根据状态标志的值返回订单id或null。这样,索引中只存储不完整的订单。这一切都很好。
我的问题是,如果我需要表中的许多其他列,并且只希望索引扫描以避免计划中的索引ROWID访问表,那么执行此操作的最佳方法是什么。假设我也想要客户id和产品id。这些值永远不会为空,所以如果我将它们添加到索引中,这意味着我不会以部分索引结束,因为空值将只为初始函数列添加,因为其他2列将始终具有值。所以我看到了基本的方法,不确定哪种方法更好。
1.我构建一个由一串函数组成的索引,所有函数都根据状态字段的值返回所需的值。
2.我保留第一列基于查看状态的函数,但我只构建了一个索引,该索引不用作谓词或过滤器的一部分,但实际上返回了一个较大的预计算json对象,该对象从索引中的第二个函数返回,并根据该函数中所有必需的值作为参数返回一个json对象,以及用于确定该函数是否返回null或json对象的状态标志。
或者也许有一种更好的方法来构建带有额外foelds的部分索引?
专家解答
第一个问题: 你真的need做任何花哨的事情?
在状态上有一个简单的索引,性能是否 “足够好”?
如果不是,则在以下位置建立一个简单的旧索引:
应该获得仅索引扫描。这 “足够好” 吗?
如果以上内容真的太慢,我只会开始做一些更深奥的事情。
如果你真的需要一个只存储感兴趣行的瘦索引,那么我会:
-为已完成的行创建所有感兴趣的列返回null的虚拟列
-索引那些
-在查询中使用虚拟列:
在状态上有一个简单的索引,性能是否 “足够好”?
如果不是,则在以下位置建立一个简单的旧索引:
create index ... on ... ( status, customer, product );
应该获得仅索引扫描。这 “足够好” 吗?
如果以上内容真的太慢,我只会开始做一些更深奥的事情。
如果你真的需要一个只存储感兴趣行的瘦索引,那么我会:
-为已完成的行创建所有感兴趣的列返回null的虚拟列
-索引那些
-在查询中使用虚拟列:
create table t as
select level tid,
case
when level > 9500 then 'TODO'
else 'DONE'
end status,
mod ( level, 31 ) product_id,
mod ( level, 79 ) customer_id,
rpad ( 'x', 100, 'x' ) stuff
from dual
connect by level <= 10000;
alter table t
add (
status_todo as ( case when status = 'TODO' then status end ),
customer_todo as ( case when status = 'TODO' then customer_id end ),
product_todo as ( case when status = 'TODO' then product_id end )
);
create index i
on t ( status_todo, customer_todo, product_todo );
select num_rows from user_indexes
where index_name = 'I';
NUM_ROWS
500
set serveroutput off
select customer_todo, product_todo
from t
where status_todo = 'TODO';
select *
from table(dbms_xplan.display_cursor(format => 'BASIC LAST'));
---------------------------------
| Id | Operation | Name |
---------------------------------
| 0 | SELECT STATEMENT | |
| 1 | INDEX RANGE SCAN| I |
--------------------------------- 文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




