最近在写一个java的爬虫程序时,遇到了一个大量数据进行插入更新和大量数据循环查询的问题,所以查了一下一般的调优的方式,下面主要介绍我采取的调优措施。

一 、调优思路

先说说我采取方式的调优的思路,这样便于理解我的选取的调优策略。

思路分析

首先我们都知道计算机存储空间分为:寄存器、高速缓存、内存、交换区(外部存储虚拟化)、硬盘以及其他的外部存储。而且我们都知道从寄存器开始到硬盘读写速度是从快到慢依次递减。我们访问数据库,一般是通过运行的代码去访问数据库,运行起来的代码所需要的数据一般会放在内存或者是在高速缓存中,而数据库数据存放在哪?很多人会说应该存放在电脑硬盘中,但是这个只回答对了一半。个人开发,代码和数据库在同一个电脑上,但是如果是团队开发喃?明显存放在个人的电脑上不合适,一般会存放在团队开发的服务器上硬盘上。团队开发时,将服务器硬盘上的数据读到自己开发电脑的内存中(自己开发测试时)或者上线后从一个数据库服务器硬盘读到上线服务器内存(数据库和程序不在一个服务器上),加上数据表查询和查询交互的一些准备(包括一些初始化)所需要的时间将会很多。

最简朴的sql插入、更新和查询一般程序一条一条的链接数据库进行操作,这样耗费的时间非常恐怖。

由此引出我们调优的想法,减少与数据库交互的次数,将多条查询,多条插入,多条更新合并为交互一次,也就是批操作。这样会减少很多时间。多次处理的操作交给java程序在内存中进行处理,内存中处理的速度要快上很多。

二、插入的优化(批插入)

将插入语句进行拼接,多条插入语句拼接成一条插入语句,与数据库交互一次执行一次。

使用insert into tableName values(),(),(),()语句进行拼接然后再一次性插入。

如果字符串太长,则需要配置下MYSQL,在mysql 命令行中运行 :set global max_allowed_packet = 2*1024*1024*10

我插入1000条的数据耗时为毫秒级别,效率提高很多。

1、下面是代码可以便于理解:

$sql= "insert into twenty_million (value) values";
for($i=0;$i<2000000;$i++){
$sql.="(''),";
};
$sql = substr($sql,0,strlen($sql)-1);
$connect_mysql->query($sql);

2、我是用java写的代码,用的是spring带的JdbcDaoSupport类写的dao层,所以粘一下代码

 public void batchInsert(List<SpdrGoldEtfPostions> spdrGoldEtfPostionsList) {
int size = spdrGoldEtfPostionsList.size();
String sql = "insert into " + TABLE_NAME + "(" + COLUMN_WITHOUT_ID + ") values";
StringBuffer sbf = new StringBuffer(sql);
for (int i = 0; i < size - 1; i++) {
sbf.append("('").append(spdrGoldEtfPostionsList.get(i).getSpdrEftId()).append("','")
.append(spdrGoldEtfPostionsList.get(i).getSpdrEftDate())
.append("',");
sbf.append(spdrGoldEtfPostionsList.get(i).getTotalNetAssetValue()).append("),");
}
sbf.append("('").append(spdrGoldEtfPostionsList.get(size - 1).getSpdrEftId()).append("','")
.append(spdrGoldEtfPostionsList.get(size - 1).getSpdrEftDate())
.append("',");
sbf.append(spdrGoldEtfPostionsList.get(size - 1).getTotalNetAssetValue()).append(")"); sql = sbf.toString();
this.getJdbcTemplate().update(sql);
}

三、更新优化(批更新)

将更新语句进行拼接,多条更新语句拼接成一条更新语句,与数据库交互一次执行一次。

1、下面是sql语句的批更新语句,提供便于理解

UPDATE book
SET Author = CASE id
WHEN 1 THEN '黄飞鸿'
WHEN 2 THEN '方世玉'
WHEN 3 THEN '洪熙官'
END
WHERE id IN (1,2,3)

2、下面java写的spring带的JdbcDaoSupport类写的dao层的批更新语句

  public void batchUpdateBySpdrEftDate(List<SpdrGoldEtfPostions> spdrGoldEtfList) {
int size = spdrGoldEtfList.size();
String sql = "UPDATE " + TABLE_NAME + " set total_net_asset_value = CASE spdr_eft_date\n";
StringBuffer sbf = new StringBuffer(sql);
for (int i = 0; i < size; i++) {
sbf.append("WHEN ").append(spdrGoldEtfList.get(i).getSpdrEftDate()).append(" THEN ")
.append(spdrGoldEtfList.get(i).getTotalNetAssetValue()).append("\n");
}
sbf.append("END\n").append("WHERE spdr_eft_date IN(");
for (int i = 0; i < size - 1; i++) {
sbf.append(spdrGoldEtfList.get(i).getSpdrEftDate()).append(",");
}
sbf.append(spdrGoldEtfList.get(size - 1).getSpdrEftDate()).append(")");
sql = sbf.toString();
this.getJdbcTemplate().update(sql);
}

四、查询优化(批量查询)

将所有的查询都合并为一条查询语句,然后返回一个集合,然后处理集合(最好返回的集合是有序的,这样处理起来比较的方便,在sql语句中可以用order by 或者group by进行排序分类,顺便多说一句,使用order by 和group by 的字段最好建立索引,这样速度更快)

1、首先写一下sql语句,便于大家理解

select * from tableName where id in (1,2,3,4) order by id

2、下面java写的spring带的JdbcDaoSupport类写的dao层的批查询语句

 public List<SpdrGoldEtfPostions> batchSelectBySpdrEtfDate(String[] spdrEtfDateArray) {
String sql = "select * from " + TABLE_NAME;
StringBuffer sbf = new StringBuffer(sql);
sbf.append(" where spdr_eft_date IN(");
for (int i = 0; i < spdrEtfDateArray.length - 1; i++) {
sbf.append(spdrEtfDateArray[i]).append(",");
}
sbf.append(spdrEtfDateArray[spdrEtfDateArray.length - 1]).append(")").append(" ORDER BY spdr_eft_date");
sql = sbf.toString();
List<SpdrGoldEtfPostions> items = this.getJdbcTemplate().query(sql, rowMapper());
return items;
}

当然批量查询你可以改变where后面的限定语句,也可以实现批量查询,如where id <100 and id>10(这里id<100写在前面也是优化的思路,这天语句在执行时,会先将范围控制在100以内,然后在从99给数据中进行查询限定,这也是优化,所以说,很多小细节都能体现优化),类似这类的也可以实现批量查询,根据需要改变限定条件实现批量查询。

五、删除的优化(批量删除)

其实看完了批量查询的话,就可以得到一些关于sql批量删除的想法了,无非是限定条件上动点手脚。

1、先给一下sql语句便于理解

delete from tableName where id in(1,2,3,4,5,6)

2、下面java写的spring带的JdbcDaoSupport类写的dao层的批删除语句

 public void batchDeleteBySpdrEtfDate(String[] spdrEtfDateArray) {
String sql = "delete from " + TABLE_NAME;
StringBuffer sbf = new StringBuffer(sql);
sbf.append(" where spdr_eft_date IN(");
for (int i = 0; i < spdrEtfDateArray.length - 1; i++) {
sbf.append(spdrEtfDateArray[i]).append(",");
}
sbf.append(spdrEtfDateArray[spdrEtfDateArray.length - 1]).append(")");
sql = sbf.toString();
this.getJdbcTemplate().update(sql); }

和查询同样道理的,可以通过设定where后面的限定,来实现其他的类批删除。

六、总结

1、首先,数据量较大的sql优化,采取的是批处理操作,减少与数据库的交互次数。

2、批处理的sql语句交给java程序去拼接,如果数据量较大时,可以考虑使用StringBuilder代替String,如果考虑线程安全可以考虑StringBuffer(或者其他安全的字符串处理类)拼接。

3、批查询的时候获取的集合数据建议排序,获取有序数据,这样便于后续java程序的处理。

4、一般的ORM框架都是用的sql语句,而一些sql语句的小的细节都能优化,使用时需要日积月累,平时应该时刻有优化意识。

5、使用过hibernate应该都知道,hibernate有缓存功能,一级二级缓存,这个思路符合我这篇博客优化思路,可以提一下,然后提供继续优化的思路,对于一些经常操作的数据可以设置高速缓存。

6、在使用sql语句的时候对于经常需要进行order by和group by的字段(列)建立索引,sql查询避免进行全表扫描,这些在写sql语句时需要注意。

简单的sql调优(批处理)的更多相关文章

  1. SQL调优常用方法

    在使用DBMS时经常对系统的性能有非常高的要求:不能占用过多的系统内存和 CPU资源.要尽可能快的完成的数据库操作.要有尽可能高的系统吞吐量.如果系统开发出来不能满足要求的所有性能指标,则必须对系统进 ...

  2. SQL调优

    # 问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  3. [SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优

    最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“'1'='1'”这个表达式永远返回 true, ...

  4. 读书笔记之SQL注入漏洞和SQL调优

    原文:读书笔记之SQL注入漏洞和SQL调优 最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“' ...

  5. SQL注入漏洞和SQL调优SQL注入漏洞和SQL调优

    SQL注入漏洞和SQL调优 最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“'1'='1'”这 ...

  6. Hive 的简单使用及调优参考文档

    Hive 的简单使用及调优参考文档   HIVE的使用 命令行界面 使用一下命令查看hive的命令行页面, hive --help --service cli 简化命令为hive –h 会输出下面的这 ...

  7. Oracle SQL调优记录

    目录 一.前言 二.注意点 三.Oracle执行计划 四.调优记录 @ 一.前言 本博客只记录工作中的一次oracle sql调优记录,因为数据量过多导致的查询缓慢,一方面是因为业务太过繁杂,关联了太 ...

  8. /*+parallel(t,4)*/在SQL调优中的重要作用!

    谈谈HINT /*+parallel(t,4)*/在SQL调优中的重要作用! /*+parallel(t,4)*/在大表查询等操作中能够起到良好的效果,基于并行查询要启动并行进程.分配任务与系统资源. ...

  9. MySQL索引和SQL调优手册

    MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree ...

随机推荐

  1. python函数知识点(详解匿名函数)

    Python函数是组织好的.单一的.具有独立功能模块的代码块. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print().但你也可以自己创建函数,这被叫做用户自定 ...

  2. python 单向链表实现

    单链表的操作 is_empty() 链表是否为空 length() 链表长度 travel() 遍历整个链表 add(item) 链表头部添加元素 append(item) 链表尾部添加元素 inse ...

  3. Scrum 冲刺 第七日

    Scrum 冲刺 第七日 站立式会议 燃尽图 今日任务安排 项目发布说明 站立式会议 返回目录 燃尽图 返回目录 今日任务安排 返回目录 项目发布说明 本版本的新功能 不只是简单打地鼠,还有一些不能打 ...

  4. android 框架LoonAndroid,码农偷懒专用

    介绍 http://www.eoeandroid.com/thread-324764-1-1.html 架构培训视频: http://pan.baidu.com/s/1mgv8HTm 简介:下载 ht ...

  5. ThreadLocal就是这么简单

    前言 今天要研究的是ThreadLocal,这个我在一年前学习JavaWeb基础的时候接触过一次,当时在baidu搜出来的第一篇博文ThreadLocal,在评论下很多开发者认为那博主理解错误,给出了 ...

  6. 详解k8s一个完整的监控方案(Heapster+Grafana+InfluxDB) - kubernetes

    1.浅析整个监控流程 heapster以k8s内置的cAdvisor作为数据源收集集群信息,并汇总出有价值的性能数据(Metrics):cpu.内存.网络流量等,然后将这些数据输出到外部存储,如Inf ...

  7. centos7 安装docker

    1.首先cent7 基本是在vm上完全安装'. 2.参考官方网站安装 1.https://wiki.centos.org/AdditionalResources/Repositories OS req ...

  8. SpringMVC之数据传递一

    之前的博客中也说了,mvc中数据传递是最主要的一部分,从url到Controller.从view到Controller.Controller到view以及Controller之间的数据传递.今天主要学 ...

  9. 容器化的 DevOps 工作流

    对于 devops 来说,容器技术绝对是我们笑傲江湖的法宝.本文通过一个小 demo 来介绍如何使用容器技术来改进我们的 devops 工作流. devops 的日常工作中难免会有一些繁琐的重复性劳动 ...

  10. Jetty入门(1-1)Jetty入门教程

    一.Jetty是什么? 1.Jetty 是一个Java语言编写的,开源的Servlet容器和应用服务器. Jetty 极度轻量级.高便携性.功能强大.灵活和扩展性好,而且支持各种技术如SPDY.Web ...