oracle命令运行速度非常慢

时间:2011-11-08 13:32:14

标签: oracle hibernate sql-order-by sql-optimization

我正在进行类似这样的查询,需要6秒才能完成:

select * 
from ( select aaa."ID" 
      from "aaa"  
      where aaa."DELETED" is null 
      order by aaa."CREATED" desc ) 
where rownum <= 15;

我的表中有大约160万条记录,我尝试在已删除的列和已创建的列中添加单独的索引,我尝试添加包含已创建和已删除的colunms的索引,并且我尝试创建相同的索引以不同的顺序排列。似乎没有任何帮助。我该怎么做才能加快速度呢?

我无法更改查询因为它是由hibernate生成的

编辑: 即使没有aaa."DELETED" is null,查询运行速度也非常慢。

编辑2: Query plan

编辑3: 添加我的索引定义。老实说,我不知道大多数这些数字是什么意思,我使用sqldeveloper来创建索引。甚至不知道每个索引有如此多的配置选项,我现在将查看文档。

CREATE INDEX "aaa"."aaa_CREATED_ASC" ON "aaa"."aaa"
  (
    "CREATED"
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;
CREATE INDEX "aaa"."aaa_CREATED_DESC" ON "aaa"."aaa"
  (
    "CREATED" DESC
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;

2 个答案:

答案 0 :(得分:9)

您需要了解Oracle如何访问数据库中的记录。索引读取是一个操作,表读取是另一个操作。因此,从表中检索一个索引记录至少需要两次读取。

您的查询使用三条信息:

  • DELETED列(限制标准)
  • CREATED列(排序标准)
  • ID(结果集)

Oracle不会对NULL值编制索引,因此DELETED上的单个列索引对您没有帮助。这是一个全表扫描,并没有比没有索引更好。

CREATED上的索引本身更好,因为访问路径将变为:

INDEX FULL SCAN DESCENDING

也就是说,它开始是索引中的最新日期并向后工作。但是,查询仍然需要读取表以查找ID和DELETED值。这可能是很多表读取,具体取决于DELETED为空的频率。

现在,(CREATED, DELETED) 上按此顺序的复合索引应该更有用,因为Oracle现在会将DELETED列中的NULL编入索引。 Oracle可以使用索引来确保它只查找表记录以获取ID值。这将是十五个表读数。

最后,您可以在(CREATED, DELETED, ID)上构建复合索引,并从索引中为整个查询提供服务。这是最快的选择。

然后,您只需确定性能优势是否证明维护索引的开销是合理的。对于它的价值而言,维护复合指数的成本只会增加一小部分列索引的成本。


顺便说一下,像这样的可怕查询是使用逻辑删除是个坏主意的一个原因。物理删除记录,并在需要时使用日记表来检索表的历史状态。

答案 1 :(得分:0)

试着看看这里

http://www.dba-oracle.com/oracle_tips_null_idx.htm

另外(尽管我怀疑它会对此有所帮助),如果生成的查询太慢,hibernate中会有本机查询。