0

invt_item_d列上的表有一个索引(item_id & branch_id & co_id)。第一个查询的计划结果是TABLE ACCESS FULL,成本是528,第二个查询的结果是INDEX FAST FULL SCAN(我的索引),成本是27

唯一的区别是,如您所见,所选列用于第二个查询的索引。

这有什么问题吗?拜托,你能告诉我我应该怎么做才能在数据库管理级别解决这个问题?

select d.qty
  from invt_item_d d 
 where d.item_id = 999 
   and d.branch_id = 888 
   and d.co_id = 777

select d.item_id
  from invt_item_d d 
 where d.item_id = 999 
   and d.branch_id = 888 
   and d.co_id = 777

编辑:我做了一个新查询,这个查询的成本是 529,表访问权限已满。

select qty from invt_item_d

所以我是否使用索引并不重要。有人说这很正常,这真的是正常行为吗?

4

3 回答 3

1

在第一种情况下,必须访问表,因为“数量”列仅存储在表中。

在第二种情况下,查询中使用的所有列都可以从索引中读取,完全跳过表读取。

您可以在列(item_id、branch_id、co_id、qty)上添加另一个索引,它很可能会在第一个查询中使用。

来自 Oracle 文档:http ://docs.oracle.com/cd/E11882_01/server.112/e25789/indexiot.htm

快速全索引扫描是一种全索引扫描,其中数据库在不访问表的情况下访问索引本身中的数据,并且数据库不按特定顺序读取索引块。

当满足以下两个条件时,快速全索引扫描是全表扫描的替代方法:

  • 索引必须包含查询所需的所有列。

  • 包含所有空值的行不得出现在查询结果集中。为保证此结果,索引中的至少一列必须具有:

    • NOT NULL 约束

    • 应用于它的谓词,防止在查询结果集中考虑空值

于 2013-08-27T08:45:00.557 回答
0

这正是使用索引的主要目的——使搜索更快。与查询没有索引的列相比,查询有索引的列更快。

它的基本预言知识。

于 2013-08-27T08:57:19.200 回答
0

我正在添加另一个答案,因为它似乎更方便。

首先:“我没有命中索引,因为有 34000 行,而不是数百万行”。这是完全错误的和危险的理解。

我的意思是,如果有几千行,并且索引没有命中(oracle 引擎执行全表扫描(TABLE ACCESS FULL)那么),这没什么大不了的。Oracle 的速度足以在一秒钟内读取几千行(即使没有索引),因此您不会感觉到差异。查询仍然较慢(比有索引的情况),但它是如此之少慢到你不会感觉到差异。但是,如果有数百万行,那么在没有索引的情况下,查询的执行将会慢得多(因为这次它将在全表扫描中扫描数百万行)并且您的性能将会受到影响。

第二:为什么你必须遍历一个有 34000 行的表,也就是 4000 次???那是一种可怕的做法。尽可能避免循环。必须有更好的方法!

第三:您可以使用索引提示强制 Oracle 优化器命中索引。您需要知道索引的名称。

select /*+ index(invt_item_d <index_name>) */
       d.qty
  from invt_item_d d 
 where d.item_id = 999 
   and d.branch_id = 888 
   and d.co_id = 777

这是关于索引提示的堆栈溢出问题的链接

于 2013-08-27T10:37:32.037 回答