--sql-1,不使用order by排序再分页,执行300多秒才出来: select * from (select t.*, rownum rn from (select a.RFID, decode(e.type, '112', e.name, sh.name) as name, to_char(d.DEATH_DATE, 'yyyy-mm-dd hh24:mi:ss'), to_char(d.DEATH_DEAL_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_TAG, d.DEATH_TYPE, to_char(d.DEATH_REG_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_RESULT, d.DEATH_REASON, d.death_change, d.death_method, d.id /* , rownum as ro */ from tbl_Death d, tbl_animal_info a, tbl_Enterprise e, tbl_Enterprise sh, tbl_Region r where d.ANIMAL_ID = a.id and a.ENTERPRISE_ID = e.id(+) and a.owner_name = to_char(sh.id(+)) and e.REGION_ID = r.id and r.code like '331082%' --order by d.id desc ) t where rownum <= 20) re where re.rn >= 1
sql-1第一次执行了300多秒才出来,第二次17秒,第三次12秒。
sql-1执行计划:(可以看到cost消耗很小,cardinality基数很大)
--sql-2,使用order by排序再分页,1秒左右出来: select * from (select t.*, rownum rn from (select a.RFID, decode(e.type, '112', e.name, sh.name) as name, to_char(d.DEATH_DATE, 'yyyy-mm-dd hh24:mi:ss'), to_char(d.DEATH_DEAL_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_TAG, d.DEATH_TYPE, to_char(d.DEATH_REG_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_RESULT, d.DEATH_REASON, d.death_change, d.death_method, d.id /* , rownum as ro */ from tbl_Death d, tbl_animal_info a, tbl_Enterprise e, tbl_Enterprise sh, tbl_Region r where d.ANIMAL_ID = a.id and a.ENTERPRISE_ID = e.id(+) and a.owner_name = to_char(sh.id(+)) and e.REGION_ID = r.id and r.code like '331082%' order by d.id desc) t where rownum <= 20) re where re.rn >= 1
sql-2第一次执行3.2秒,后面都是0.4秒内就出来了。
sql-2执行计划:(可以看到cost消耗较小,cardinality基数变很小了)
以前看执行计划,以为只要看cost消耗小,sql就会执行很快,现在看来cardinality基数的影响也是很大的。
--sql-3 是sql-1不分页,内层的sql,执行很快1秒内。 select a.RFID, decode(e.type, '112', e.name, sh.name) as name, to_char(d.DEATH_DATE, 'yyyy-mm-dd hh24:mi:ss'), to_char(d.DEATH_DEAL_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_TAG, d.DEATH_TYPE, to_char(d.DEATH_REG_DATE, 'yyyy-mm-dd hh24:mi:ss'), d.DEATH_DEAL_RESULT, d.DEATH_REASON, d.death_change, d.death_method, d.id /* , rownum as ro */ from tbl_Death d, tbl_animal_info a, tbl_Enterprise e, tbl_Enterprise sh, tbl_Region r where d.ANIMAL_ID = a.id and a.ENTERPRISE_ID = e.id(+) and a.owner_name = to_char(sh.id(+)) and e.REGION_ID = r.id and r.code like '331082%'
sql-3执行速度基本和sql-2一样。
sql-3执行计划:(可以看到cost消耗和cardinality基数,基本和排序了的sql-2在一个数量级)
总结分析:不用order by排序而分页,oracle需要耗费更多来记住这个无序的排序,以用以分页。而已经按索引列排序的字段order by后,减少了这个过程。所以使用order by反而加快了实际查询速度。
ps:有高手看到的话希望能提点一下:sql-1第一次执行300多秒,后面接着执行几次变成了10秒多出来,这是oracle的什么缓存机制吗?想知道具体是oracle的什么样的原理机制。这也是线上系统经常遇到的一个问题,第一次点sql执行太久,不出结果,过一会再点就可以了。