我正在进行类似这样的查询,需要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:
编辑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" ;
答案 0 :(得分:9)
您需要了解Oracle如何访问数据库中的记录。索引读取是一个操作,表读取是另一个操作。因此,从表中检索一个索引记录至少需要两次读取。
您的查询使用三条信息:
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中会有本机查询。