if not exist的灾难性后果

     最近做了一个asp.net的网站,其中数据库操作用到了一个存储过程,此存储过程的作用是将一条数据插入数据库的一个表,但是要保证不能重复插入。我原来的方法没用到存储过程,只用到了一条SQL插入语句,并且将表中五个字段作为键,因为只有这五个字段同时作为键才可以确定一条数据的唯一性。然后插入的时候如果碰到重复会违反数据库键重复的原则从而达到不重复插入的目的。

     后来由于一个负责人不知道出于什么原因将数据库重新做了调整,并且搞了一堆的存储过程,而且主要的是把一个自动生成递增的index作为新的键,这可怎么判断插入重复啊?他的方法是在存储过程中通过用一条if not exist语句来判断库里面是否有重复,然后紧接着通过上面if not exist语句的判断结果来执行插入语句。

      当从这个存储过程来看,感觉也看不出有什么区别,但是当需要循环插入上万条数据时,巨大的区别便出现了,本来说存储过程可以提高效率嘛,但这里的存储过程比我单条的SQL要慢多了,具体时间我也没计算。据我分析,这效率变低的主要原因就在于那条if not exist语句,执行这条语句需要多少时间呢?

      于是我便在循环插入数据的那段C#代码前后加上获取系统时间的函数,通过比较前后时间差来获得执行数据库操作到底用了多少时间。通过实验12700条数据,直接用SQL插入的代码花了21s,用存储过程而没用if not exist花了17s,而加上了if not exist的那个存储过程用了2m55s。数据库内原有71700条数据。

      根据if not exist的自然语言含义,这条命令应该是要遍历数据库每条数据来判断是否存在重复数据。当数据库规模不断增大,这条指令的执行效率也将越来越低,到后期可能会造成灾难性的影响。为了验证我的想法,我将数据库内的数据增加了差不多一倍到了148000条左右,再执行前面提到的三个方案,前两者时间不变,if not exist的那个存储过程也才2m59s,没有我想象的久。经过分析,由于我插入的数据是重复的数据,所以当if not exist语句遍历到了原来那条数据的位置便停止遍历,而这个位置在70000条之前,故并没有遍历整个数据库,所以要验证这种灾难性的影响,我又取了一组没插入的数据,共15400条左右,等了半天,居然用了8m41s。再用没有if not exist的版本重复插入,花了21s,真是天差地别。

      这真把我这个数据库新手吓坏了,因为项目已经基本完工了,之前的速度一直也在客户的容忍范围内,但是不把那条if not exist语句改成别的方案的话,随着数据库的增大,那基本上比较恐怖。看来改动是必须的了,而这却要伤及整个项目的框架,最讨厌伤筋动骨的事情了,而这个框架却是负责这项目的两个老师搭的(注:本人是学生),这是相当郁闷的,早期设计的时候居然未考虑到这么个严重的问题,不知道各位看官有没碰过类似的问题,如果通过设置键来防止重复效率会更高吗?还是要另求他法了?

------------------------------------------------------------------------

      经过刚才几小时候的调试,现在已经成功地消除了if not exist语句的影响,主要是因为在插入上万条数据时,这些数据都是成千条地罗列于一个文件中,而只要通过判断文件中前两个是否已经插进去,即在读取前两条数据的时候,使用带if not exist那个存储过程,然后通过判断前两条数据是否插入数据库来决定之后的数据是否要插入,这里分两种情况:1.前两条数据插入了数据库,说明这个文件以前未读取过,后面的数据都不会是重复数据,即只要调用不带if not exist的存储过程;2.前两条数据未插入数据库,说明这个文件以前读取过,后面的数据也将是重复的数据,所以这里只要跳出这个文件读取的while循环便可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值