精华内容
下载资源
问答
  • 数据库插入缓慢
    2021-02-03 15:10:33

    问题:

    前段时间用了scrapy + mysql,mysql 开始是装在固态硬盘上的,所以采集的速度很快,之后换了电脑,把 mysql 装在机械硬盘上,导致爬取速度下降的太明显了,但是硬盘写入时就满载的,机械硬盘就导致了写入瓶颈,所以就做了一个数据库插入速度对比。

     

    爬取(不是导入哦)数据量:4200 行

     

    1. mysql

    机械硬盘的 mysql 插入:7-8分钟左右

    固态硬盘的 mysql 插入:40-50秒左右

     

    2. mongodb

    机械硬盘的 mongodb 插入:88秒左右

    固态硬盘的 mongodb 插入:33秒左右

     

    更多相关内容
  • 一、编写测试案例向MySQL数据库插入百万条数据。测试数据表建表脚本如下:use db_xk; drop table if exists tb_test2; create table tb_test2 ( id int primary key auto_increment, subject varchar(50) ...
  • 最近的项目需要导入大量的数据,插入的过程中还需要边查询边插入插入的数据量在100w左右。一开始觉得100w的数据量不大,于是就插啊插,吃了个饭,回来一看,在插入了50多w条数据后,每秒就只能插10条了。。觉得很...

    最近的项目需要导入大量的数据,插入的过程中还需要边查询边插入。插入的数据量在100w左右。一开始觉得100w的数据量不大,于是就插啊插,吃了个饭,回来一看,在插入了50多w条数据后,每秒就只能插10条了。。觉得很奇怪,为啥越插越慢呢?  于是就开始分析插入的时间损耗,想到了如下的解决方案:(mysql使用的INNODB引擎)

    1.分析是否是由主码,外码,索引造成的插入效率降低

    主码:由于主码是每张表必须有的,不能删除。而mysql会对主码自动建立一个索引,这个索引默认是Btree索引,因此每次插入数据要额外的对Btree进行一次插入。这个额外的插入时间复杂度约为log(n)。这个索引无法删除,因此无法优化。但是每次插入的时候,由于主码约束需要检查主码是否出现,这又需要log(n),能否减少这个开销呢?答案是肯定的。我们可以设置主码为自增id  AUTO_INCREMENT ,这样数据库里会自动记录当前的自增值,保证不会插入重复的主码,也就避免了主码的重复性检查。

    外码:由于我的项目的插入表中存在外码,因此每次插入时需要在另一张表检测外码存在性。这个约束是与业务逻辑相关的,不能随便删除。并且这个时间开销应当是与另一张表大小成正比的常数,不应当越插入越慢才对。所以排除。

    索引:为了减少Btree插入的时间损耗,我们可以在建表时先不建索引,先将所有的数据插入。之后我们再向表里添加索引。该方法确实也降低了时间的开销。

    经过以上的折腾,再进行测试,发现速度快了一点,但是到了50w条后又开始慢了。看来问题的关键不在这里。于是继续查资料,又发现了个关键问题:

    2.将单条插入改为批量插入(参考:点击打开链接)

    由于java中的executeUpdate(sql)方法只是执行一条sql操作,就需要调用sql里的各种资源,如果使用for循环不停的执行这个方法来插入,无疑是开销很大的。因此,在mysql提供了一种解决方案:批量插入。 也就是每次的一条sql不直接提交,而是先存在批任务集中,当任务集的大小到了指定阈值后,再将这些sql一起发送至mysql端。在100w的数据规模中,我将阈值设置为10000,即一次提交10000条sql。最后的结果挺好,插入的速度比之前快了20倍左右。批量插入代码如下:

    public static void insertRelease() {

    Long begin = new Date().getTime();

    String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";

    try {

    conn.setAutoCommit(false);

    PreparedStatement pst = conn.prepareStatement(sql);

    for (int i = 1; i <= 100; i++) {

    for (int k = 1; k <= 10000; k++) {

    pst.setLong(1, k * i);

    pst.setLong(2, k * i);

    pst.addBatch();

    }

    pst.executeBatch();

    conn.commit();

    }

    pst.close();

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    Long end = new Date().getTime();

    System.out.println("cast : " + (end - begin) / 1000 + " ms");

    }

    3.一条UPDATE语句的VALUES后面跟上多条的(?,?,?,?)

    这个方法一开始我觉得和上面的差不多,但是在看了别人做的实验后,发现利用这个方法改进上面的批量插入,速度能快5倍。后来发现,mysql的导出sql文件中,那些插入语句也是这样写的。。即UPDATE table_name (a1,a2) VALUES (xx,xx),(xx,xx),(xx,xx)... 。也就是我们需要在后台自己进行一个字符串的拼接,注意由于字符串只是不停的往末尾插入,用StringBuffer能够更快的插入。下面是代码:

    public static void insert() {

    // 开时时间

    Long begin = new Date().getTime();

    // sql前缀

    String prefix = "INSERT INTO tb_big_data (count, create_time, random) VALUES ";

    try {

    // 保存sql后缀

    StringBuffer suffix = new StringBuffer();

    // 设置事务为非自动提交

    conn.setAutoCommit(false);

    // Statement st = conn.createStatement();

    // 比起st,pst会更好些

    PreparedStatement pst = conn.prepareStatement("");

    // 外层循环,总提交事务次数

    for (int i = 1; i <= 100; i++) {

    // 第次提交步长

    for (int j = 1; j <= 10000; j++) {

    // 构建sql后缀

    suffix.append("(" + j * i + ", SYSDATE(), " + i * j

    * Math.random() + "),");

    }

    // 构建完整sql

    String sql = prefix + suffix.substring(0, suffix.length() - 1);

    // 添加执行sql

    pst.addBatch(sql);

    // 执行操作

    pst.executeBatch();

    // 提交事务

    conn.commit();

    // 清空上一次添加的数据

    suffix = new StringBuffer();

    }

    // 头等连接

    pst.close();

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    // 结束时间

    Long end = new Date().getTime();

    // 耗时

    System.out.println("cast : " + (end - begin) / 1000 + " ms");

    }

    做了以上的优化后,我发现了一个很蛋疼的问题。虽然一开始的插入速度的确快了几十倍,但是插入了50w条数据后,插入速度总是会一下突然变的非常慢。这种插入变慢是断崖式的突变,于是我冥思苦想,无意中打开了系统的资源管理器,一看发现:java占用的内存在不断飙升。 突然脑海中想到:是不是内存溢出了?

    4.及时释放查询结果

    在我的数据库查询语句中,使用到了pres=con.prepareStatement(sql)来保存一个sql执行状态,使用了resultSet=pres.executeQuery来保存查询结果集。而在边查边插的过程中,我的代码一直没有把查询的结果给释放,导致其不断的占用内存空间。当我的插入执行到50w条左右时,我的内存空间占满了,于是数据库的插入开始不以内存而以磁盘为介质了,因此插入的速度就开始变得十分的低下。因此,我在每次使用完pres和resultSet后,加入了释放其空间的语句:resultSet.close(); pres.close();。重新进行测试,果然,内存不飙升了,插入数据到50w后速度也不降低了。原来问题的本质在这里!

    这个事情折腾了一天,也学到了很多。希望这篇博客能帮助到大家!

    展开全文
  • mysql并发选择插入数据库速度慢

    千次阅读 2021-01-19 22:54:19
    这个表与我必须从中读取数据的表相同,有时整个数据库由于选择数据而变得很慢,同时还有许多挂起的插入。我把索引放在我在where语句中使用的每个字段上,所以我真的不知道为什么select变得如此缓慢。有人能给我一个提示...

    我有一个很大的mysql表(大约5米行),我经常在上面插入数据。

    这个表与我必须从中读取数据的表相同,有时整个数据库由于选择数据而变得很慢,同时还有许多挂起的插入。

    我把索引放在我在where语句中使用的每个字段上,所以我真的不知道为什么select变得如此缓慢。

    有人能给我一个提示来解决这个问题吗?

    这是表和查询的SQL

    CREATE TABLE `messages` (

    `id` int(10) unsigned NOT NULL auto_increment,

    `user_id` int(10) unsigned NOT NULL default '0',

    `dest` varchar(20) character set latin1 default NULL,

    `body` text character set latin1,

    `sent_on` timestamp NOT NULL default CURRENT_TIMESTAMP,

    `md5` varchar(32) character set latin1 NOT NULL default '',

    `interface` enum('mobile','desktop') default NULL,

    PRIMARY KEY (`id`),

    KEY `user_id` (`user_id`),

    KEY `md5` (`md5`),

    FULLTEXT KEY `dest` (`dest`,`body`),

    FULLTEXT KEY `body` (`body`)

    ) ENGINE=MyISAM AUTO_INCREMENT=7074256 DEFAULT CHARSET=utf8

    这里的问题是:

    EXPLAIN SELECT SQL_CALC_FOUND_ROWS id, sent_on, dest AS who, body,interface FROM messages WHERE user_id = 2 ORDER BY sent_on DESC LIMIT 0,50 \G;

    *************************** 1. row ***************************

    id: 1

    select_type: SIMPLE

    table: messages

    type: ref

    possible_keys: user_id

    key: user_id

    key_len: 4

    ref: const

    rows: 13997

    Extra: Using where; Using filesort

    1 row in set (0.00 sec)

    展开全文
  • 多线程插入(单表) 问:为何对同一个表的插入多线程会比单线程快?同一时间对一个表的写操作不应该是独占的吗? 答:在数据里做插入操作的时候,整体时间的分配是这样的: 链接耗时 (30%) 发送query到服务器 ...

    多线程插入(单表)

    问:为何对同一个表的插入多线程会比单线程快?同一时间对一个表的写操作不应该是独占的吗?

    答:在数据里做插入操作的时候,整体时间的分配是这样的:

    • 链接耗时 (30%)

    • 发送query到服务器 (20%)

    • 解析query (20%)

    • 插入操作 (10% * 词条数目)

    • 插入index (10% * Index的数目)

    • 关闭链接 (10%)

    从这里可以看出来,真正耗时的不是操作,而是链接,解析的过程。

    MySQL插入数据在写阶段是独占的,但是插入一条数据仍然需要解析、计算、最后才进行写处理,比如要给每一条记录分配自增id,校验主键唯一键属性,或者其他一些逻辑处理,都是需要计算的,所以说多线程能够提高效率。

    多线程插入(多表)

    分区分表后使用多线程插入。

    预处理SQL

    • 普通SQL,即使用Statement接口执行SQL

    • 预处理SQL,即使用PreparedStatement接口执行SQL

    使用PreparedStatement接口允许数据库预编译SQL语句,以后只需传入参数,避免了数据库每次都编译SQL语句,因此性能更好。

    String sql = "insert into testdb.tuser (name, remark, createtime, updatetime) values (?, ?, ?, ?)";
    for (int i = 0; i < m; i++) {
        //从池中获取连接
        Connection conn = myBroker.getConnection();
        PreparedStatement pstmt = conn.prepareStatement(sql);
        for (int k = 0; k < n; k++) {
                pstmt.setString(1, RandomToolkit.generateString(12));
                pstmt.setString(2, RandomToolkit.generateString(24));
                pstmt.setDate(3, new Date(System.currentTimeMillis()));
                pstmt.setDate(4, new Date(System.currentTimeMillis()));
                //加入批处理
                pstmt.addBatch();
        }
        pstmt.executeBatch();    //执行批处理
        pstmt.close();
        myBroker.freeConnection(conn); //连接归池
    }
    

    多值插入SQL

    • 普通插入SQL:INSERT INTO TBL_TEST (id) VALUES(1)

    • 多值插入SQL:INSERT INTO TBL_TEST (id) VALUES (1), (2), (3)

    使用多值插入SQL,SQL语句的总长度减少,即减少了网络IO,同时也降低了连接次数,数据库一次SQL解析,能够插入多条数据。

    事务(N条提交一次)

    在一个事务中提交大量INSERT语句可以提高性能。

    1. 将表的存储引擎修改为myisam
    2. 将 sql 拼接成字符串,每 1000 条左右提交事务。
    /// <summary>
            /// 执行多条SQL语句,实现数据库事务。
            /// </summary>mysql数据库
            /// <param name="SQLStringList">多条SQL语句</param>
            public void ExecuteSqlTran(List<string> SQLStringList)
            {
                using (MySqlConnection conn = new MySqlConnection(connectionString))
                {
                    if (DBVariable.flag)
                    {
                        conn.Open();
                        MySqlCommand cmd = new MySqlCommand();
                        cmd.Connection = conn;
                        MySqlTransaction tx = conn.BeginTransaction();
                        cmd.Transaction = tx;
                        try
                        {
                            for (int n = 0; n < SQLStringList.Count; n++)
                            {
                                string strsql = SQLStringList[n].ToString();
                                if (strsql.Trim().Length > 1)
                                {
                                    cmd.CommandText = strsql;
                                    cmd.ExecuteNonQuery();
                                }
                                //后来加上的
                                if (n > 0 && (n % 1000 == 0 || n == SQLStringList.Count - 1))
                                {
                                    tx.Commit();
                                    tx = conn.BeginTransaction();
                                }
                            }
                            //tx.Commit();//原来一次性提交
                        }
                        catch (System.Data.SqlClient.SqlException E)
                        {
                            tx.Rollback();
                            throw new Exception(E.Message);
                        }
                    }
                }
            }
    

    10w条数据大概用时10s!

    展开全文
  • 文章目录Python连接DB2使用ibm_db和ibm_db_sa两个包使用ibm_db_sa和sqlalchemy两个包Python处理插入数据库报数据类型不一致问题Python执行SQL语句成功但是数据库没有数据Python插入大体量数据时到一定数量崩溃 ...
  • postgresql数据库写入数据缓慢或者停止的问题背景...经过dba的排查发现原因为,大量数据的更新导致PG库的表膨胀问题,表膨胀后未及时触发pg的垃圾回收机制,导致插入需要耗费大量的cpu资源,从而造成数据库性能不佳 二.
  •  23、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌INsert来插入(不知JAVA是否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储过程...
  • 好吧,也许我完全错过了一些东西,但我刚刚开始使用SQL和Android,并且从我所看到的更新和插入数据库需要单独处理?我可以检索包含多个记录的游标,但是如果我想将更新应用于游标中的每个记录,我只能看到如何单独...
  • 数据库和旧数据库,创建一模一样的测试表数据300万条,数据一模一样。都没有索引。 执行同一条删除sql语句,旧数据执行4分钟结束,新数据库20分钟结束。 由于不是专业dba折腾了很久。 问题排查如下: 1、生成...
  • 通常来说C++操作MySQL的时候,往Mysql中插入10000条简单数据,速度非常缓慢,居然要5分钟左右, 而打开事务的话,一秒不到就搞定了! 具体实现代码如下: #include #include #include #include "mysql.h" #...
  • 今天讨论的内容是冷热分离,也许概念并不陌生,对其使用场景也比较熟悉,但涉及...比如业务员多次查询时,数据库的 CPU 会立马狂飙,服务器线程也降不下来。 当时,我们尝试了优化表结构、业务代码、索引、SQL 语句等.
  • 它通过调用PreparedStatementMetaData.getParameterMetaData()这显然会导致一个“准备”语句被发送到数据库本身,它本身是非常快的(从不超过我的笔记本电脑上的1ms),但是它被称为每行的每一列这总结了很多时间(它是...
  • 公司有一个项目,需要频繁的插入数据到MySQL数据库中,设计目标要求能支持平均每秒插入1000条数据以上。目前功能已经实现,不过一做压力测试,发现数据库成为瓶颈,每秒仅能插入100多条数据,远远达不到设计目标。到...
  • 最近新的项目写了不少各种 insertBatch 的代码,一直有人说,批量插入比循环插入效率高很多,那本文就来实验一下,到底是不是真的? 测试环境: SpringBoot 2.5 Mysql 8 JDK 8 Docker 首先,多条数据的插入,可选的...
  • 从Delphi 2010到远程MySQL 5.09服务器的插入速度非常慢,这是一个主要的问题.到目前为止,我已经尝试过:>使用MySQL ODBC驱动程序的ADO> Zeoslib v7 Alpha> MyDAC我已经使用ADO进行批处理和直接插入(使用表...
  • http://www.oracleplus.net/arch/1278.html 以下是工具的用法 Oracle 10046跟踪事件使用方法 https://www.cnblogs.com/abclife/p/5295862.html tkprof用法 ... ...
  • mysql插入数据变慢的原因

    千次阅读 2021-01-27 05:10:57
    最近的项目需要导入大量的数据,插入的过程中还需要边查询边插入插入的数据量在100w左右。一开始觉得100w的数据量不大,于是就插啊插,吃了个饭,回来一看,在插入了50多w条数据后,每秒就只能插10条了。。觉得很...
  • 你向 MySQL 数据库插入 100w 条数据用了多久? 转载:https://mp.weixin.qq.com/s?__biz=MzUxOTc4NjEyMw==&mid=2247484796&idx=1&sn=79adb1422664467fd5c5f167f888bcdb&chksm=f9f51e98ce82978e94...
  • Oracle插入很慢,性能优化排查方案(可能存在的问题-等待事件)
  • 大事务造成线上insert插入缓慢 问题描述 最近有用户反馈,线上很多订单下单特别慢,每天集中在早上9-10点钟,我跟踪生产tomcat日志,发现一段insert sql执行时间大概要60s的样子。怀疑应该是生产有大事务执行导致表...
  • 一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢,下面我们来看mysql千万级数据库插入速度和读取速度的调整记录吧。     (1)提高数据库插入性能中心思想:尽量将数据一...
  • 盘点数据库慢查询的12个原因

    千次阅读 2022-05-30 17:08:32
    日常开发中,我们经常会遇到数据库慢查询。那么导致数据慢查询都有哪些常见的原因?大家聊聊导致数据库慢查询的12个常见原因,以及对应的解决方法。 1. SQL没加索引 很多时候,我们的慢查询,都是因为没有加索引...
  • (1、首先明确一点,如果每条数据需要一秒的时间,假如是一亿条数据至少需要2年左右,意味着你两年都不能使用这个数据库,在现实生活中,你认为可能这样做吗? 2、解决这类问题的最好办法就是:时间换空间,例如:...
  • 1.没有索引或者没有用到索引(程序设计缺陷) 2.I/O吞吐量小,形成了瓶颈效应 3.没有创建计算列导致查询不优化 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询降低数据量) ...
  • 通过在 MATLAB 中构造 INSERT 字符串,可以将数据(缓慢地)插入数据库中。 它可以同时连接到多台服务器(或多个连接到一台服务器)。 有关使用说明,请参阅 mysql.m。 使用前必须编译; 简要说明在 C++ 文件中或...
  • mysql优化小结(插入和查询)说到mysql,我们立刻想起它体积小、速度快、还开源的特点,所以它应用颇广。今天我们来总结一下mysql中最频繁的两个操作:插入和查询,的优化方法。插入:一、文本导入使用LOAD DATA IN...
  • 数据库实现原理

    千次阅读 2021-08-16 19:58:53
    /** * 最简单的数据库 */ public class SimplestDB { // 数据库文件名 private static final String DB_FILE_NAME = "./db/db.dat"; public static void main(String[] args) throws ParseException, IOException {...
  • 6000多条数据update如果单纯使用save需要... * 使用数据库原生的方式执行,不需要配置 * @param list */ public void batchWithNativeSql(List<User> list) throws SQLException { String sql = "Insert into
  • 上一篇聊到过,冷热分离解决方案的性价比高,但它并不是一个最优的方案,仍然存在诸多不足,比如:查询冷数据慢、业务无法再修改冷数据、冷数据多到... 原文链接:数据库表数据量大读写缓慢如何优化(2)【查询分离】

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,383
精华内容 6,953
关键字:

数据库插入缓慢