zoukankan      html  css  js  c++  java
  • sql server编写简洁四则运算表达式脚本实现计算批次(或计算分页数)功能(C#等其它编程语言也能直接用此通用表达式)

    问题:
      在数据库编程开发中,有时会遇到数据量比较大的情况,如果直接大批量进行添加数据、修改数据、删除数据,就会是比较大的事务,事务日志也比较大,耗时久的话会对正常操作造成一定的阻塞。虽不至于达到删库跑路的程度,但也严重影响了用户体验,老是卡巴死机的感觉。这时我们可以对这个大批量操作进行分小批事务操作处理,使每批时间比较短,减少阻塞。大而化小,小而化了。举个例子:如果大批事务需要跑5分钟,那就阻塞了5分钟;如果分成10个小批,每小批0.5分钟,那就降低了长时间阻塞的几率,提高了用户体验。
      把目光放宽广一点,其实不只是在数据库编程,有时候我们也需要在其他编程语言中,实现分批处理的逻辑,例如使用C#对大批量Excel数据进行处理。
      对于如何求批次这个问题,我们当然是希望有统一的计算公式,不管是什么编程语言都通用的,而不是换种编程语言,就得根据不同编程语言的语法重新实现这个算法。以达到快速开发目的,一次写的表达式,去到哪里都能通用。
      而求批次(或求分页数)这个问题有点像初中代数的求解:
      已知总数据量a,每批(或每页)数据量为b,求所需批次(或所需总页数)x?
      假设a为388888,b为10000。

    解决方案:
    方法1(不推荐)
    如果是数据库编程,可能大部分人的思维习惯就是:
    先用a / b得出除得尽部分,例如这里是38;
    然后再用case when去判断a % b除不尽部分也就是余数是否为0,如果不为0,则批次加1,例如这里是8888,虽然不够10000,但是也不在38个批次之内,需要在第39批次。
    使用T-SQL实现:@a / @b + case when @a % @b > 0 then 1 else 0 end
    缺点:

    • 很明显这样的表达式比较长,不是很简洁。
    • 而且如果改用C#实现,可是不支持case when的,得重新修改表达式实现功能。

    方法2(推荐):
    可以直接根据四则运算,表达式为(@a + @b - 1) / @b
    这个表达式,是博主自己想到的方法,解释如下:
    由于序号是从1开始,第1批是从1到10000,而不是从0到9999,所以这里@a - 1,就是为了从编程习惯的角度由序号0开始;
    而 + @b则是因为,0到9999中任意一个数字,除以每批数据量10000的话,都是 < 1,但实际是当1批了,需要加回。

    优点:

    • 单纯使用四则运算,无需case when等条件判断,代码简洁。
    • 方便代码移植到C#等其他语言,只需要把参数改成相应C#变量之类,无需把case when改成C#能支持的if之类条件判断。

    方法3推荐
    可以直接根据四则运算,表达式为(@a - 1) / @b + 1
    这个表达式,也是博主自己想到的方法,解释如下:
    由于序号是从1开始,第1批是从1到10000,而不是从0到9999,所以这里@a - 1,就是为了从编程习惯的角度由序号0开始;
    而 + 1则是因为,0到9999中任意一个数字,除以每批数据量10000的话,都是 < 1,但实际是当1批了,需要加回。
    优点:

    • 单纯使用四则运算,无需case when等条件判断,代码简洁。
    • 方便代码移植到C#等其他语言,只需要把参数改成相应C#变量之类,无需把case when改成C#能支持的if之类条件判断。

    方法2和方法3,从代数的角度看,关系式是等价的:
    方法2关系式去掉括号后是:@a / @b + 1 - 1 / @b
    方法3关系式去掉括号后是:@a / @b - 1 / @b + 1

    脚本:

    /*
        问题:已知总数据量a,每批数据量为b,求所需批次x?假设a为388888,b为10000。
        脚本来源:https://www.cnblogs.com/zhang502219048/p/11108723.html
    */
    declare @a int = 388888,
            @b int = 10000,
            @x1 int,
            @x2 int,
            @x3 int
    
    --方法1(不推荐):除了四则运算外,还有取模运算,而case when条件判断更是使脚本变得长而复杂,也不利于移植到其他编程语言
    select @x1 = @a / @b + case when @a % @b > 0 then 1 else 0 end
    
    --方法2(推荐):只使用四则运算就实现
    select @x2 = (@a + @b - 1) / @b
    
    --方法3(推荐):只使用四则运算就实现
    select @x3 = (@a - 1) / @b + 1
    
    --查看计算结果
    select @x1 as x1, @x2 as x2, @x3 as x3

    在博主的上一篇技术博文《sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日期》,说明了怎么批量生成连续数字,我们就直接生成10W数据量来验证一下本篇博文《sql server编写简洁四则运算表达式脚本实现计算批次功能(C#等其它编程语言也能直接用此通用表达式)》所述的计算批次表达式是否正确。
    问题扩展到:
    已知总数据量a,每批数据量为b,求每条数据所属批次x?假设a为100000,b为1000。
    验证脚本:

    /*
        问题:已知总数据量a,每批数据量为b,求每条数据所属批次x?假设a为100000,b为1000。
        作者:zhang502219048
        脚本来源:https://www.cnblogs.com/zhang502219048/p/11108723.html
        脚本基于:https://www.cnblogs.com/zhang502219048/p/11108991.html
    */
    declare @a int = 100000,
            @b int = 1000
    
    select vid
        --方法1(不推荐):除了四则运算外,还有取模运算,而case when条件判断更是使脚本变得长而复杂,也不利于移植到其他编程语言
        , x1 = vid / @b + case when vid % @b > 0 then 1 else 0 end
        --方法2(推荐):只使用四则运算就实现
        , x2 = (vid + @b - 1) / @b
        --方法3(推荐):只使用四则运算就实现
        , x3 = (vid - 1) / @b + 1
    into #t
    from fun_ConcatStringsToTable(1,@a)
    
    --查看所有数据和所属批次
    select * from #t
    --检查批次计算结果是否一致
    select distinct case when x1 = x2 and x2 = x3 then 'Right!' else 'Wrong!' end as Result
    from #t
    
    drop table #t

    验证脚本运行结果:


    总结:
    博主对于计算批次的新思路就介绍到这里,大家如果觉得有用的话可以直接拿来用,是不是觉得很方便呢?感觉为批次计算的算法注入了新的思想,标新立异。

    【转载请注明博文来源:https://www.cnblogs.com/zhang502219048/p/11108723.html

  • 相关阅读:
    推荐系统 蒋凡译 第一章 引言 读书笔记
    神经网络与深度学习 邱锡鹏 第5章 卷积神经网络 读书笔记
    神经网络与深度学习 邱锡鹏 第4章 前馈神经网络 读书笔记
    神经网络与深度学习 邱锡鹏 第3章 线性模型 读书笔记
    神经网络与深度学习 邱锡鹏 第2章 机器学习概述 读书笔记
    神经网络与深度学习 邱锡鹏 第1章 绪论 作业
    神经网络与深度学习 邱锡鹏 第1章 绪论 读书笔记
    算法笔记 上机训练实战指南 第13章 专题扩展 学习笔记
    算法笔记 第13章 专题扩展 学习笔记
    算法笔记 上机训练实战指南 第11章 提高篇(5)--动态规划专题 学习笔记
  • 原文地址:https://www.cnblogs.com/zhang502219048/p/11108723.html
Copyright © 2011-2022 走看看