Rownum和命令的执行顺序造成的影响

  

  月的某天下午,某用户反馈,医生站首页中病案附加项目的顺序乱了,影响医生的正常工作。   

  

  从跟踪出来的看的到,执行得到的数据没有按预期的方式排序,但是,相同的在测试库运行却能得到正常排序的结果。   

  

     

  

     

  

  院方近期没有做什么调整,怀疑跟一个月前我们转移历史数据之前的一系列性能优化调整有关。   

  

  经过一番分析,最终,通过重新收集该涉及到的表的统计信息后,问题得到解决。   

  

  感觉有点儿不可思议吧?   

  

  统计信息收集不正确,还会影响产品功能的正常性?   

  

     

  

  有些事情的真相并不是我们看到那样,就像鸡血在磨心上点了几下之后,小孩的肚子就不痛了,如果你相信这样的巫术,可能会影响到你对很多事情的判断,有时,我们看到的并不一定是真相,倒不是因为对未知的知识缺乏敬畏,而是基本的逻辑推理问题,以及探寻真相的钻研精神。   

  

     

  

  统计信息收集确实是解决很多性能问题的一副灵药,但对这个问题来说,收集统计信息只是其中的一种临时解决办法,根本的原因还是书写方面存在问题。   

  

  下面我们来一步一步解开事情的真相。   

  

  语句如下:   

  

  序号编码名称内容病案项目编码   

  

     

  

  多么简单的,不像那些需要翻几页才能看得完整的变态,这种简单的除了理解起来更节约时间之外,还减少了很多可能导致验证结果偏差的干扰。   

  

  按开发人员的预期,先排序再对结果集进行编号,作为下特有的“伪列”,作用就是根据数据结果行数产生一个从开始递增的行号。   

  

     

  

  有一定基础的同学可能一下就看出的不对之处:   

  

  和在同一层次时,排序是最后执行的,先取行号自然就无法得到想要的按排序结果递增的行号,所以,如下所示,序号列就是“乱序”的。   

  

     

  

  那么,问题来了,既然这个有问题,为什么在测试库运行又是正常的呢?   

  

  近期产品中的这条也没有做过修改,为什么以前是正常的,现在却突然出现问题了呢?   

  

  没有骗你哟,用户发来了测试库上执行后结果正确的截的图。   

  

     

  

  刚开始看到这个现象,也是很纳闷,会不会是数据库的什么参数影响了排序,像经常遇到的“_gby_hash_aggregation_enabled”这个参数对排序的影响(后续可能会写一个这方面的案例),问题是这个里没有子句。   

  

  
  

  

  从数据库的基础理论方面想了想,影响排序的还有哪些因素呢?   

  

  如果是有索引,那么索引本身就是排了序的,读取数据时就不需要排序了,再用取值,是不是就可以取到预期的结果了呢?   

  

  也就是说,变相实现了先排序,后取序号的作用。   

  

     

  

  为了证实这一点,在公司的测试库上做了一个验证:   

  

  相同的,执行结果跟用户测试库的结果是一样的,序号正常排序。   

  

  禁用主键”病案项目”以“编码”字段为索引后,执行结果跟用户正式库的结果一样,序号排序就乱了,再现了问题。   

  

  病案项目病案项目   

  

  恢复主键后,序号就正常排序了。   

  

  病案项目病案项目   

  

     

  

  是不是用户生产库的主键被禁用了,索引丢了吗?   

  

  转移历史数据期间,的确会禁用一些约束,但是这张表并不是转出相关的表呀!而且转完数据后,我们恢复约束后也做过检查。   

  

  会不会是用户后期运行过程中,某种原因导致该索引无效了呢?   

  

  马上查询用户的生产库,主键是有效的,索引也是有效的。   

  

     

  

  眼看找到一条路,没想到走到底发现是个死胡同,不要懈气,既然问题再现了,原理也清楚了,顺着这条路,仔细找,找一定有出路。   

  

     

Rownum和命令的执行顺序造成的影响