2

我正在做这样的查询,需要 6 秒才能完成:

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

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

我无法更改查询,因为它是由休眠生成的

编辑:即使没有aaa."DELETED" is null查询运行也很慢。

编辑2: 查询计划

编辑 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" ;
4

2 回答 2

9

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

您的查询使用三条信息:

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

Oracle 不索引 NULL 值,因此单列索引对DELETED您没有帮助。那是全表扫描,根本不比没有索引好。

单独的索引CREATED更好,因为访问路径将变为:

INDEX FULL SCAN DESCENDING

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

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

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

然后,您只需要确定性能优势是否证明维护索引的开销是合理的。就其价值而言,维护复合索引的成本只增加了维护单列索引的成本的一小部分。


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

于 2011-11-08T14:20:24.383 回答
-1

试着看这里

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

此外(尽管我怀疑它在这里会有所帮助),如果生成的查询太慢,休眠中有本机查询。

于 2011-11-08T13:39:49.840 回答