索引字段顺序对效率的影响

个人总结几点:

1、驱动表中的索引要将区间字段(sendtime之类)放到固定值(orgid等)的后面

2、驱动表的连接字段可以放在索引最后,以避免读取rowid

3、连接表的连接字段要放在索引最前面。


举个例子:

selectcount(*)as col_0_0_

  fromREC_BANKINSTRUCTION batchrecba0_

 crossjoinREC_BILL_DETAIL batchrecbi1_

 wherebatchrecbi1_.ID = batchrecba0_.BILLDETAILID

   andbatchrecba0_.ORGID = batchrecbi1_.ORGID

   andbatchrecba0_.STATUS = :1

   andbatchrecba0_.ORGID = :2

   andbatchrecba0_.SENDTIME >= :3

执行计划:



现有索引结构:

 

 

索引优化:

dropindexREC_BANK_QUERY_INDEX;

createindexREC_BANK_QUERY_INDEX onREC_BANKINSTRUCTION(ORGID,SENDTIME,CREATETIME, STATUS, BILLDETAILID);

dropindexREC_BILL_ORGID;

createindexREC_BILL_ORGID onREC_BILL_DETAIL(ORGID,IMPORTDATE,ID);

 

优化之后执行计划:


优化之后索引结构:

 


以上并没有考虑索引字段的顺序问题

 

但是,sql是从REC_BANKINSTRUCTION loop到REC_BILL_DETAIL

所以,首先应确定REC_BANKINSTRUCTION的索引,应该是status\orgid\sendtime三个字段,然后把billdetailid包含进来

第一个索引存在两个问题:

    1、sendtime应该往后放,这样索引数据将会聚集,减少io。如果sendtime往前放,那么status不是索引,而是筛选,io增大

    建议顺序为orgid\status\sendtime,至于createtime可以放着,是用于筛选的,当前没有用到

    2、REC_BILL_DETAIL是通过orgid\id关联的,那么这两个字段必须放前面,如你现在索引,则ID变成了筛选,而非索引

    建议顺序orgid\id\importdate,importdate是包含字段,可以用于筛选,可以用于显示

  

因此,先对REC_BILL_DETAIL的索引顺序更改:

dropindexREC_BILL_ORGID;

createindexREC_BILL_ORGID onREC_BILL_DETAIL(ORGID,ID,IMPORTDATE);

更改后索引为:


执行计划为:

 

可以看到对REC_BILL_DETAIL的join查询有了明显提高。

 

再更新REC_BANKINSTRUCTION表的索引:

dropindexREC_BANK_QUERY_INDEX;

createindexREC_BANK_QUERY_INDEX onREC_BANKINSTRUCTION(ORGID,STATUS,SENDTIME, CREATETIME, BILLDETAILID);

 

索引为:

 

执行计划为:

 

Instruction表的扫描有了明显提高。


你可能感兴趣的:(DB)