暂无图片
组合索引问题
我来答
分享
lu9up的数据库笔记
2023-09-19
组合索引问题

oracle中,为什么order by的字段要放在联合索引的最后?

我来答
添加附件
收藏
分享
问题补充
6条回答
默认
最新
广州_老虎刘

严格来说没有放到最后的说法. 有几种情况:

1.如果经过where条件过滤后返回的结果集比较小, 索引不包含order by字段, 做个排序也没关系; 

2.如果过滤条件都是等值条件,而且返回的结果集有点大, 为了避免排序, order by字段确实是放到最后; 

3.如果过滤条件含有非等值条件, 比如>,< , like , <> 等, 这个时候order by 字段就不是最后,而是非等值条件放到最后(减少回表) , 这种组合索引的创建原理叫ESR(equal,sort,range)理论. 

4. 如果返回列较少,可以再把返回列加上,,成ESRR,那就是在组合索引的最后增加返回列.  形成覆盖索引, 能进一步减少回表.    

具体使用什么样的索引, 归根结底还是要根据表上各字段的数据分布决定.

暂无图片 评论
暂无图片 有用 1
打赏 1
暂无图片
lu9up的数据库笔记
题主
2023-09-19
大佬,能解释一下原理吗?
lnn

提高查询性能,减少排序操作开销

暂无图片 评论
暂无图片 有用 4
打赏 0
张sir

由于索引是有序的,对于一个组合索引(a,b,c),首先是按a排序,在a相同的情况下,按b排序,在a,b都相同的情况下,按c排序。再一个查询中where a=1and b=2 order by c。这个时候记录是按c排序的,可以利用索引的有序性,直接返回记录,无需再进行排序。

暂无图片 评论
暂无图片 有用 3
打赏 0
Rocky

首先联合索引中的各列都是排序的,前导列和后面的where中的过虑掉数据,过滤后留下的数据就是需要的数据,因为order by已经在索引中排序,这样就利用索引消除了排序。有时为了减少回表,会将select后的列放在索引最后。

暂无图片 评论
暂无图片 有用 2
打赏 0
Thomas

对此我有点疑惑:

create table t (c1 varchar2(10),c2 varchar2(10),c3 varchar2(10));

insert into t values ('a','b','h');
insert into t values ('x','y','a');
insert into t values ('a','b','c');
commit;
create index idx_t on t(c1,c2,c3);
那么idx_t索引内容应该如下
a b c 第三行rowid
a b h 第一行rowid
x y a 第二行rowid

select * from t where c1='a' and c2='b' order by c3;
那么filter时走索引idx_t,因为c3是联合索引的后部列,所以filter后的次序就是按c3排序的,无须再排序。

drop index idx_t;
create index idx_r on t(c3,c1,c2);
那么idx_r索引内容应该如下
x y a 第二行rowid
a b c 第三行rowid
a b h 第一行rowid

select * from t where c1='a' and c2='b' order by c3;
那么filter时仍走索引idx_r, 因为c3是联合索引的前导列,所以filter后的次序就是按c3排序的,也无须再排序。

既然两种情况都可以省略掉排序这步,为什么说c3列必须在联合索引的后部?

暂无图片 评论
暂无图片 有用 1
打赏 0
lu9up的数据库笔记
题主
2023-09-19
第一种c3列在组合索引后面情况,我试了一下是不用回表做filter的: -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 42 | 1 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| IDX_T | 2 | 42 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("C1"='a' AND "C2"='b') 第二种c3列为引导列,有回表: -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 42 | 1 (0)| 00:00:01 | |* 1 | INDEX FULL SCAN | IDX_R | 2 | 42 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("C1"='a' AND "C2"='b') filter("C1"='a' AND "C2"='b')
Thomas

第二种有回表?我没看出来啊。如果有,应该有access table by rowid字样,可是第二种的执行计划里并没有啊。

暂无图片 评论
暂无图片 有用 0
打赏 0
Rocky
2023-09-21
第二个是走index full scan 你可以再这个表多加几列并且设置成char类型 将表数据加到百万以上,实际上就是创造一个大表 再观察下结果 是不是变成TABLE ACCESS FULL + SORT ORDER BY 但是如果返回数据量较少的情况下,还是可以走第一个索引的
回答交流
Markdown


请输入正文
提交
相关推荐
如何快速的从千万级别数据表查找多条数据
回答 4
建一个临时表,只存这些ID值,然后分别在两个表上建上对应的索引,做个表连接就行。类似于:selectb.id,a.fromtable1aleftjointable2bona.idb.id;这个b表就是
Oracle rac 磁盘组名称冲突怎么解决?
回答 1
1、多半之前安装过RAC或者使用过ASM磁盘组,ASM磁盘上的元数据还存在;2、检查下ASM磁盘对应的磁盘路径,【确保磁盘上没有数据,或磁盘上的数据可以清理】如:假设ASM磁盘对应的路径为:/dev/
oracle大表增加字段需要注意什么
回答 6
已采纳
我测试了一把,如果这个字段存在业务定义,在线直接加可能会出现问题,见下面的测试文章https://www.darkathena.top/archives/aboutaddcolonline
Oracle删除怎么查出操作者的主机或者IP?
回答 2
你可以按照搂上的方法找到会话,根据会话ID或者sqlid在v$activesessionhistory里有MACHINE,PROGRAM显示主机名可操作数据的客户端会话程序类型,要定位IP还是得结合外
为什么pl/sql中和sqlplus中看到的字段属性不一致,FD_AI,FD_THEME sqlplus显示可为空,pl/sql显示不可为空
回答 2
在create&nbsp;table时,如果你的not&nbsp;null约束不是直接写在字段后面,&nbsp;而是通过check或constraint子句增加的,&nbsp;通过sqlplus都不会
oracle有没有方案可以实现多个库的数据同步到一个库中
回答 1
已采纳
看你具体需求,方案还是挺有的。ogg,SharePlex,dsg,12c的refreshpdb
Oracle rman设置保留策略只有一天,但是看备份集,一个月前的还在,这是为什么?
回答 2
你看到一个月前还在是指,没有被标记为expired还是已经标记了没有删除。如果标记为expired,是需要手动删除的。
oracle单项选择题(恢复)
回答 6
答案是A、current和active联机redolog文件,也可能需要归档redolog文件。在Oracle中,实例恢复通常需要使用以下类型的redolog文件:当前(current)联机redol
oracle可以限制system、sys用户只能在数据库服务器上登录,其他ip登录不了吗?有什么比较建议的方法吗?
回答 1
已采纳
SHOWPARAMETERREMOTELOGINPASSWORD;值为:exclusive时,启用口令文件,允许远程登录;值为:NONE时,停用口令文件验证,Oracle数据库不允许远程SYSDBA/
Oracle里有没有超时设置,如果某语句(dml居多)执行的时间太长(如30秒),跳过它,然后返回一个超时错误?
回答 7
这个好像没有吧,没听说过,有也不敢用