首页 > 数据库 >SQL批量插入的优化心得

SQL批量插入的优化心得

时间:2024-07-23 11:28:41浏览次数:14  
标签:插入 批量 posi variety item SQL 心得

pkgRiskDataVOList = mapper.getBuyAndSaleFee(ImmutableMap.ofEntries(kv("iTradeDate", iTradeDate)));
                    String fnFmtNumber16 = pkiPub.fnFmtNumber(pkgRiskDataVOList.getBuyFee(), 6);
                    String fnFmtNumber17 = pkiPub.fnFmtNumber(pkgRiskDataVOList.getSaleFee(), 6);

在把存储过程改成sql+java。老sql中定义了函数来对结果进行trim之后批量插入,但是新的sql考虑到迁移性没有定义函数。所以在java中进行了trim,但这样的话就没法用原来批量插入的sql。新sql只有单行插入。本来要用循环的,但是考虑到清算需要效率,所以考虑用foreach改写:

                    List<PkgRiskDataVO> pkgRiskDataVOList = mapper.getLongAndShortAmtAndTodayPrice(ImmutableMap.ofEntries(kv("iTradeDate", iTradeDate), kv("vCapitalTotalAccount", vCapitalTotalAccount)));
                    String finalVCapitalTotalAccount = vCapitalTotalAccount;
                    List<Map<String, Object>> formattedSqlParams = pkgRiskDataVOList.stream().map(pkgRiskDataVO -> {
                        String fnFmtNumber10 = pkiPub.fnFmtNumber(pkgRiskDataVO.getLongAmt(), 6);
                        String fnFmtNumber11 = pkiPub.fnFmtNumber(pkgRiskDataVO.getShortAmt(), 6);
                        String fnFmtNumber12 = pkiPub.fnFmtNumber(pkgRiskDataVO.getTodayPrice(), 6);
                        Map<String, Object> dataMap = new HashMap<>();
                        dataMap.put("fnFmtNumber10", fnFmtNumber10);
                        dataMap.put("fnFmtNumber11", fnFmtNumber11);
                        dataMap.put("fnFmtNumber12", fnFmtNumber12);
                        dataMap.put("cnSplitChar", cnSplitChar);
                        dataMap.put("cnFiCdp", cnFiCdp);
                        dataMap.put("iTradeDate", iTradeDate);
                        dataMap.put("vCapitalTotalAccount", finalVCapitalTotalAccount);
                        return dataMap;
                    }).collect(Collectors.toList());

                    rowcountGen = mapper.spGenRiskinitdataSql13(formattedSqlParams);

sql

 <insert id="spGenRiskinitdataSql13" parameterType="map">
        INSERT INTO tmp_data_gen (ROWNUM, COLUMN2, CN_FI_CV)
        <foreach collection="list" item="item" separator=",">
            SELECT ROWNUM,
            TRIM(cust_no) || #{item.cnSplitChar} || TRIM(variety_code) ||
            #{item.cnSplitChar} || long_posi || #{item.cnSplitChar} ||
            #{item.fnFmtNumber10} || #{item.cnSplitChar} ||
            short_posi || #{item.cnSplitChar} ||
            #{item.fnFmtNumber11} || #{item.cnSplitChar} ||
            #{item.fnFmtNumber12} || #{item.cnSplitChar} || '0' ||
            #{item.cnSplitChar} || TRIM(bank_acc),
            #{item.cnFiCdp}
            FROM (SELECT a.cust_no,
            d.bank_acc,
            a.variety_code,
            a.long_posi,
            a.long_posi * c.today_price * b.exch_unit long_amt,
            a.short_posi,
            a.short_posi * c.today_price * b.exch_unit short_amt,
            c.today_price
            FROM cli_defer_hold a,
            defer_variety b,
            settle_price c,
            cust_basicinfo d
            WHERE a.tx_date = TRIM(#{item.iTradeDate})
            AND a.variety_code = b.variety_code
            AND a.tx_date = c.tx_date
            AND a.variety_code = c.variety_code
            AND a.cust_no = d.cust_no
            AND a.cust_no != #{item.vCapitalTotalAccount}
            AND NOT (nvl(a.long_posi, 0) = 0 AND nvl(a.short_posi, 0) = 0)
            UNION ALL
            SELECT a.cust_no,
            d.bank_acc,
            a.variety_code,
            a.long_posi,
            a.long_posi * c.today_price * b.exch_unit long_amt,
            a.short_posi,
            a.short_posi * c.today_price * b.exch_unit short_amt,
            c.today_price
            FROM cli_quote_hold a,
            quote_variety b,
            settle_price c,
            cust_basicinfo d
            WHERE a.tx_date = TRIM(#{item.iTradeDate})
            AND a.variety_code = b.variety_code
            AND a.tx_date = c.tx_date
            AND a.variety_code = c.variety_code
            AND a.cust_no = d.cust_no
            AND a.cust_no != #{item.vCapitalTotalAccount}
            AND NOT (nvl(a.long_posi, 0) = 0 AND nvl(a.short_posi, 0) = 0))
        </foreach>
    </insert>

在数据库操作中,使用 foreach 在 SQL 语句中进行批量插入,比在 Java 层的循环中一次次地调用 SQL 语句要高效得多。以下是原因:

  1. 数据库连接和资源管理

    在 Java 层的循环中调用 SQL:每次调用 SQL 都需要建立数据库连接、执行语句、处理结果,然后关闭连接。这会导致大量的开销,包括网络延迟、连接管理开销等。
    使用 foreach 进行批量插入:批量操作只需要一次数据库连接和执行。这减少了大量的连接开销和网络延迟。

  2. 网络开销

    在 Java 层的循环中调用 SQL:每次调用 SQL 都需要通过网络传输数据。对于大量数据,这会导致网络带宽的消耗和延迟。
    使用 foreach 进行批量插入:批量操作可以一次性传输所有数据,极大地减少了网络传输的次数和带宽消耗。

  3. 事务管理

    在 Java 层的循环中调用 SQL:每次 SQL 操作都是一个独立的事务,数据库需要为每个操作进行事务管理。这会导致事务管理的开销。
    使用 foreach 进行批量插入:所有插入操作都在一个事务中完成,数据库只需要处理一次事务管理,极大地提高了效率。

  4. 数据库优化

    在 Java 层的循环中调用 SQL:数据库无法对单独的插入操作进行优化。
    使用 foreach 进行批量插入:数据库可以对批量操作进行优化,例如通过批量插入的机制来减少写入磁盘的次数,提高写入速度。

性能比较

在 Java 层的循环中调用 SQL:假设需要插入 1000 条记录,每条记录需要花费 10ms 的网络和连接管理时间,总共需要 1000 * 10ms = 10秒。
使用 foreach 进行批量插入:假设批量插入 1000 条记录只需要花费 1秒。相比之下,性能提升非常明显。

标签:插入,批量,posi,variety,item,SQL,心得
From: https://www.cnblogs.com/peterzh/p/18317949

相关文章

  • 智能停车场系统--前后端分离(可直接落地)使用数据:vue,springBoot,redis,mybatis,mysql等
    系统首页-统计停车车收费收费数据展示实现代码:对菜单控制代码@AutowiredprivateMenuServicemenuService;@AutowiredprivateRoleMenuServiceroleMenuService;@GetMapping("/list")publicResultlist(){List<MenuRoleVO>menuRoleList=this.menuServi......
  • MySQL server has gone away
    环境:Os:Centos7DB:mysql5.7.39 导入大量数据的时候报错误:[root@localhost~]#mysql-hlocalhost-uroot-pmysql--default-character-set=utf8-Ddev_test</tmp/db_test_20240723mysql:[Warning]Usingapasswordonthecommandlineinterfacecanbeinsecure.......
  • 在MySQL中 Truncate Delect Drop 的区别
    在MySQL中TruncateDelectDrop的区别 面试问题:----请详细描述MySQL中TRUNCATETABLE、DELETEFROM和DROPTABLE三个命令的区别,包括它们的作用、性能影响、事务日志的生成以及对表结构和触发器的影响。----回答:----在MySQL中,TRUNCATETABLE、DELETEFROM和DRO......
  • Java 支持的数据类型与 MySQL 支持的数据类型对比
    Java支持的数据类型与MySQL支持的数据类型对比整数类型:Java:byte,short,int,longMySQL:TINYINT,SMALLINT,INT,BIGINT对应关系:byte对应MySQL的TINYINTshort对应MySQL的SMALLINTint对应MySQL的INTlong对应MySQL的BIGINT浮点数类型:Java......
  • postgresql 导出数据字典文档
    在PostgreSQL中,数据字典(或称系统目录)是由一系列的系统表组成,这些表包含了数据库对象的元数据,例如表、索引、视图、函数、触发器等。要导出数据字典文档,实际上是导出这些系统表中的信息。尽管PostgreSQL并没有直接提供一个工具来一次性生成完整的数据字典文档,但是你可以使用......
  • spring使用mysql数据库实现关键字别字、拼音、拼音首字母、拼音所有首字母组合搜索
    1、实现思路前端传入的文字、拼音、别字、拼音首字母、拼音所有首字母组合传入到后台,通过后台接口转成拼音,然后通过转换后的拼音结合sql语句查询匹配。2、后台实现pom配置:<!--中文转拼音--><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4......
  • 如何使用 Python Flask 将新的咖啡馆(元素)添加到数据库(SQLite)?
    这是我的代码:@app.route("/add",methods=["POST"])defpost_new_cafe():new_cafe=Cafe(name=request.form.get("name"),map_url=request.form.get("map_url"),img_url=request.form.get("img......
  • MySQL 索引的存储结构
    Author:ACatSmilingSince:2024-07-22索引的存储结构为什么使用索引索引是存储引擎用于快速找到数据记录的一种数据结构。常将索引比作教科书的目录部分(实际上不是完全一样),通过目录找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一样的道理,进行数据查找时,首先查......
  • MySQL 索引的设计原则
    Author:ACatSmilingSince:2024-07-22索引的创建与设计原则索引的声明与使用索引的分类MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。从功能逻辑上说,索引主要有4种:普通索引、唯一索引、主键索引、全文索引。按照物理实现方式,索引......
  • SQL注入之waf绕过
    SQL注入之waf绕过(safedog)本地部署apache和safedog后,对sqllab的一个实验payload:?id=1'and1=1--+,发现被拦截了,但是不知道拦截的关键词是什么这里把1=1删了试试发现有报错,再加上1=1但是不加空格试试。报错了,这里可能是识别到and后紧跟空格和字符的模式,并把它过滤掉了pa......