建议提高查询性能(Oracle)

时间:2018-06-18 15:42:18

标签: sql performance oracle11g

我有一张表(A),有116,317,979条记录,每天增加约750,000条记录。

根据我的要求,我希望使用日期列从表中有效地获取最后3个完整日数据(日期时间存储在列中)。所以查询将是

select * from A where date_column >= trunc(sysdate) - 3

我还需要将表A加入表B,以便

select * from A 
left outer join B 
on A.X = B.X and A.Y = B.Y and A.Z = B.Z and B.M = 'XYZ' and B.N = 'UIM'
where A.date_column >= trunc(sysdate) - 3
  

唯一索引&表B的PK(X,Y,Z,M,N)

     

唯一索引&表A的PK(ID)

  

表A中提出的IDX 1(date_column)

     

表A(X,Y,Z)中建议的IDX 2

Time without Indexes 34 sec
Time with IDX 1      32 sec
Time with IDX 1 & 2  27 sec //Sorry about the mistype

通过仅在A.date_column上添加索引,我认为我可以显着提高性能,但我的测试结果是否定的。除了添加新索引之外,还有其他提示可以提高性能吗?从长远来看,添加这样的索引是否有任何危害。

最好创建另一个表并以某种方式在其中填充最近3天的数据(使用db触发器)。我可以轻松地使用另一个流程来清除每晚3天以上的数据。

提前致谢。

2 个答案:

答案 0 :(得分:2)

Oracle分区在这里很有意义,但即使对于Enterprise Edition,这也是一个额外的成本选择。 如果分区不可用 - 保留最近3天的单独表应该是最佳的性能。你应该试一试。

如果你想从索引中获得最大值,那么你可以考虑使用物理参数:

  • 如果日期列未更新且数据很少被删除,则可以设置PCTFREE 0
  • 查看您的最终查询,我建议在trunc(date)列上创建索引并使用compression - >在这种情况下,每个索引数据块存储更多条目。在这种情况下,最终查询条件应为trunc(date_column) >= trunc(sysdate) - 3

根据表A中X,Y,Z的选择性,压缩它们也是有意义的。所以我建议检查两个案例:

  1. create index trunc_date_ai on A(trunc(date_column)) pctfree 0 compress; +您的IDX2
  2. create index trunc_date_ai on A(trunc(date_column),X,Y,Z) pctfree 0 compress; 如果表A中未更新X,Y,Z,则应使用pctfree 0。 这里compress关键字对所有4列进行压缩,因此如果X,Y,Z值在表A中对于特定的trunc(date_column)具有高度可重复性,则值得使用。
  3. 要强制使用索引,您可以提示查询,例如:

    select --+ index (A trunc_date_ai)
           * 
    from   A left outer join B 
    on A.X = B.X and A.Y = B.Y and A.Z = B.Z and B.M = 'XYZ' and B.N = 'UIM'
    where trunc(A.date_column) >= trunc(sysdate) - 3
    

答案 1 :(得分:1)

您应该检查执行计划以查看是否正在使用索引。我猜测date_column上的索引没有被使用,32到34秒之间的差异只是噪音。

对于此查询,我建议使用A(date_column, X, Y, Z)的索引。

添加索引有害吗?好吧,它们增加了insert s / update s / delete s的开销。如果您的插入是事务性的,那么您每秒插入大约10行 - 不计算更新和删除。如果您的峰值明显高于,那么您的硬件不是很好,那么索引可能会减慢速度。如果批量添加额外的行,我不会担心开销。

我怀疑将桌子拆分成一个单独的3天桌子会产生很大的不同。但为什么要听我说话?试试看。获取最近3天以上的数据,将其转储到表中,正确索引并查看查询是否更快。