首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MySql批量插入-Windows10任务管理器上的磁盘使用率为100%

MySql批量插入-Windows10任务管理器上的磁盘使用率为100%
EN

Stack Overflow用户
提问于 2018-07-09 20:06:38
回答 1查看 853关注 0票数 0

我正在尝试使用MySQL批处理预准备语句插入多行。

我在本地机器上测试:安装了MySQL Server8.0和Eclipse Photon的Windows10。

当代码开始批处理时,我的笔记本电脑性能会变慢。查看TaskManager,我发现磁盘使用率达到了100%。

如果我停止在Eclipse上运行,磁盘使用就会正常化,性能问题也就消失了。它总是发生在我试图运行我的代码的时候。

我不确定问题是出在我的代码上,还是出在我的笔记本电脑上,因为当我打开我的笔记本电脑,用mysql启动windows时,我也遇到了同样的问题。我需要等待几分钟,直到我的磁盘使用率恢复正常并开始使用我的笔记本电脑。

代码语言:javascript
运行
复制
private static final String CONNECTION_STRING = "jdbc:mysql://localhost/parser?user=root&password=root&useTimezone=true&serverTimezone=UTC";

MySQLAccess(boolean debug) throws ClassNotFoundException, SQLException{
    Class.forName("com.mysql.cj.jdbc.Driver");
    connect = DriverManager
            .getConnection(CONNECTION_STRING);

    isDebug = debug;
}

private void insertLogTable(List<Map<String, Object>> logList) throws SQLException{
    String sql = "INSERT INTO log (date, ip, request, status, userAgent) VALUES (?, ?, ?, ?, ?)";

    PreparedStatement ps = connect.prepareStatement(sql);

    int i = 0;
    for (Map<String, Object> log : logList) {

        ps.setString(1, getMySQLDateString((Date)log.get("date")));
        ps.setString(2, (String)log.get("ip"));
        ps.setString(3, (String)log.get("request"));
        ps.setString(4, (String)log.get("status"));
        ps.setString(5, (String)log.get("userAgent"));

        ps.addBatch();
        i++;

        if (i % 1000 == 0 || i == logList.size()) {
            ps.executeBatch(); // Execute every 1000 items.
            debug(getMySQLDateString((Date)log.get("date")));
        }
    }

    ps.close();
}

public void close() {
    try {
        if (connect != null) {
            connect.close();
        }
    } catch (Exception e) {

    }
}

编辑:

我运行"SELECT @@innodb_buffer_pool_size“,得到'8388608‘。

我的笔记本电脑有8 8GB的内存。

代码语言:javascript
运行
复制
CREATE TABLE `log` (
  `date` datetime NOT NULL,
  `ip` varchar(15) NOT NULL,
  `request` varchar(20) NOT NULL,
  `status` varchar(3) NOT NULL,
  `userAgent` varchar(256) NOT NULL,
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `logcol` varchar(45) DEFAULT NULL,
  `logcol1` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ip_index` (`ip`),
  KEY `date_index` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=915169 DEFAULT CHARSET=utf8mb4     COLLATE=utf8mb4_0900_ai_ci;

已解决:我根据这个问题解决了这个问题How to improve performance with executeBatch?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-10 07:19:49

my.cnf中,更改为

代码语言:javascript
运行
复制
innodb_buffer_pool_size = 4G

适用于您的8 8GB机器。然后重启mysql。

由于RAM中缺少缓存,您当前的8M设置会导致大量的I/O。

(如果4G对于其他运行的设备来说太大了,可以选择其他数字,但至少尝试300M。)

我很惊讶Win 10只有8G。

我很惊讶8.0版本一开始只有8M。您是否继承了很久以前的设置(当时8M是默认设置)?我认为5.5版本在2010年将默认值提升到了1.28亿!

更多分析:

ip上的索引可能占用40MB左右。而且,我假设,IP地址是相当随机的?每次插入新行时,都会更新ip的索引。也就是说,40MB中的一个块(大小为16KB)被读取、修改并存储回磁盘。假设随机访问和40MB:8MB,那么80%的获取-修改-写入操作需要命中磁盘。也就是说,对于每1000行的簇,仅针对ip索引就有800*2个磁盘命中。此外,对于“顺序”写入的数据和其他索引,也会有一些命中(较少的命中)。我猜大概有20*1的磁盘命中率。

这只是一个粗略的计算。但它指出,如果你的buffer_pool超过40MB (假设至少100MB,考虑到我没有提到的各种因素),那么几乎所有的I/O都将消失。所有的东西都会被缓存,因此不需要“抓取”。并且“写入”可以被延迟,而不必重新进行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51245204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档