Sql 从索引中删除行ID,然后尝试按块访问行,以改进集群并减少数据库必须访问块的次数
它通过减少命中每个块的次数来更有效地检索实际数据(假设实际数据分布意味着存在多行具有相关数据的块)。但结果是检索到的数据不一定按索引顺序排列,因此需要显式排序 当我们使用索引获取rowid时,我们将以相同的顺序从数据库中获取所有数据。这是我的期望 对于批处理的Sql 从索引中删除行ID,然后尝试按块访问行,以改进集群并减少数据库必须访问块的次数,sql,oracle,sorting,optimization,indexing,Sql,Oracle,Sorting,Optimization,Indexing,它通过减少命中每个块的次数来更有效地检索实际数据(假设实际数据分布意味着存在多行具有相关数据的块)。但结果是检索到的数据不一定按索引顺序排列,因此需要显式排序 当我们使用索引获取rowid时,我们将以相同的顺序从数据库中获取所有数据。这是我的期望 对于批处理的访问,情况不再如此 问题是,即使没有必要这样做,也会增加额外的成本 但这是必要的;而且,您没有看到成批访问带来的成本降低(如前所述,这取决于实际的数据分布)。你不能孤立地看待一个成本价值。乐观主义者通常知道它在做什么。(我认为这个暗示根本没
访问,情况不再如此
问题是,即使没有必要这样做,也会增加额外的成本
但这是必要的;而且,您没有看到成批访问带来的成本降低(如前所述,这取决于实际的数据分布)。你不能孤立地看待一个成本价值。乐观主义者通常知道它在做什么。(我认为这个暗示根本没有影响到这一点,但我同意@XING的观点,即你不应该拥有它——除非你真的确定你知道乐观主义者不知道的事情)
值得注意的是,即使11g版本没有显示显式排序(根据@XING的演示),Oracle也从未保证订单结果将在没有order by
子句的情况下返回,并且通过索引ROWID进行简单的表访问(即非批处理
)优化程序只是能够跳过显式排序,因为它已经知道数据是按该顺序检索的。这就是你在评论中提到的
在11g中,如果不使用order by
子句,您可能会按照所需的顺序返回行,但这只是因为Oracle如何获取索引rowid,然后逐行获取相应数据的实现细节。但这并不能保证。这种暗箱操作的变化正是为什么即使看起来是多余的,也要明确地按
排序始终是明智的。正如您在当前代码中所做的那样。但这并不是多余的,也从来不是真的
(在早期版本中,group by也存在类似的“问题”;它通常意味着排序顺序(我想最多9次),人们忽略了顺序,但后来乐观主义者改变了(我想是10g),这让人们被忽略了……)问题出在会话的NLS\U语言
和NLS\U区域
参数中。
默认情况下,我的会话
NLS\U语言=“俄语”
NLS_地区=“俄罗斯”
当我尝试在查询中使用varchar索引值和orderby按特定顺序获取数据时,我会在查询计划中获得额外的排序依据
在我更改这些参数之后:
NLS\U语言='AMERICAN'
NLS\U地区=“美国”
在我的查询计划中,我没有获得额外的排序规则
现在,提问:
解释从SIEBEL_CT.A中选择*的计划,其中fieldB>按fieldB的“低”和“高”顺序
解释SIEBEL_CT.A中的select*计划,其中fieldB>为“低”字段,fieldB
具有相同的查询计划问题在于会话的NLS\U语言
和NLS\U区域
参数。
explain plan for select /*+ index(a)*/ * from A a where fieldB > 'LOW' and fieldB < 'HIGH' order by fieldB
默认情况下,我的会话
NLS\U语言=“俄语”
NLS_地区=“俄罗斯”
当我尝试在查询中使用varchar索引值和orderby按特定顺序获取数据时,我会在查询计划中获得额外的排序依据
在我更改这些参数之后:
NLS\U语言='AMERICAN'
NLS\U地区=“美国”
在我的查询计划中,我没有获得额外的排序规则
现在,提问:
解释从SIEBEL_CT.A中选择*的计划,其中fieldB>按fieldB的“低”和“高”顺序
解释SIEBEL_CT.A中的select*计划,其中fieldB>为“低”字段,fieldB
拥有相同的查询计划您的查询中有ORDERBY子句,因此无法避免。如果您想避免,您需要从查询中删除orderby
子句@XING,问题是我需要保证数据将按特定顺序返回。如果我按删除订单
,我将丢失此订单。但我的目标是通过使用默认的B-树索引升序来实现相同的逻辑,而不使用
orderby
。但这对我不起作用。所以,我不明白为什么优化器会选择重新排序数据,即使我希望返回的数据的顺序与生成索引的顺序相同。如果您只从查询中选择fieldB,会发生什么?@AllanS.Hansen,嗯,我按我想要的升序获取数据。但是,我如何才能在没有order by的情况下,不仅选择字段B,还选择其他字段?而且,如果我从order by fieldB asc中选择字段B,我将在查询计划中获得排序依据,但是我将以与不使用
orderby
相同的顺序获取数据,并且在查询计划中不使用任何排序子句查询中有orderby子句,因此无法避免。如果您想避免,您需要从查询中删除orderby
子句@XING,问题是我需要保证数据将按特定顺序返回。如果我按删除订单
,我将丢失此订单。但我的目标是通过使用默认的B-树索引升序来实现相同的逻辑,而不使用orderby。但这对我不起作用。所以,我不明白为什么优化器会选择重新排序数据,即使我希望返回的数据的顺序与生成索引的顺序相同。如果您只从查询中选择fieldB,会发生什么?@AllanS.Hansen,嗯,我按我想要的升序获取数据。但是,我如何才能做到这一点呢
explain plan for select /*+ index(a)*/ * from A a where fieldB > 'LOW' and fieldB < 'HIGH' order by fieldB
explain plan for select /*+ index(a)*/ * from A a where fieldB > 'LOW' and fieldB < 'HIGH' order by fieldB
SELECT STATEMENT
SORT ORDER BY
TABLE ACCESS BY INDEX ROWID BATCHED
INDEX RANGE SCAN
create table A (
fieldA numeric,
fieldB varchar(255),
fieldC varchar(255)
);
create index indx on A(fieldB);
select * from A a where fieldB > 'LOW' and fieldB < 'HIGH' order by fieldB ;
Plan Hash Value : 4131509220
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 271 | 0 | |
| * 1 | FILTER | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | A | 1 | 271 | 1 | 00:00:01 |
| * 3 | INDEX RANGE SCAN | INDX | 1 | | 1 | 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 1 - filter(NULL IS NOT NULL)
* 3 - access("FIELDB">'LOW' AND "FIELDB"<'HIGH')
Note
-----
- dynamic sampling used for this statement