【问题标题】:How do I make my function for testdata for my database faster?如何使我的数据库测试数据函数更快?
【发布时间】:2020-09-02 13:11:49
【问题描述】:

我想创建测试数据并编写了一个用于存储产品的函数,我的产品生成器在我的数据库中生成。

该计划是为了测试目的创建大约 10,000,000 个或更多产品。

我想在每次插入产品之前检查是否存在相同的产品名称。

如果是,则产品不会存储在数据库中。 我知道性能问题是检查产品是否存在,数据库中的产品越多,这需要的时间就越长。但我知道,没有其他办法可以改善这个问题。 我可能会使用索引,但我不知道如何在这种情况下使用。 如果您对如何提高性能有其他想法,请随时评论您的想法。

tldr:我想创建 testdata,但它确实需要很长时间,因为它正在检查产品是否已经存在。想要提高性能。

这是我的代码:

   public String insertProdukt(String name, Double preis, Integer kat_id) throws SQLException, ClassNotFoundException {
    Connection connection = ConnectionUtils.createNewConnection();
    // does the product exist?
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("select * from pro_produkte where pro_name=\"" + name + "\" AND pro_preis=\"" + preis + "\" AND pro_kat_id=\"" + kat_id + "\"");

    if (resultSet.next()) {
        //it does exist
        System.out.println("Produkt: " + resultSet.getString("pro_name") + " existiert bereits");
    } else {
        //it dosen't -> insert into database
        String sql = "Insert INTO pro_produkte (pro_name, pro_preis, pro_kat_id)"
                + "VALUES (\"" + name + "\", \"" + preis + "\", \"" + kat_id + "\")";
        statement.executeUpdate(sql);
        System.out.println("Produkt: " + name + " erstellt");

    }
    resultSet.close();
    statement.close();
    connection.close();
    return null;
}

谢谢!

【问题讨论】:

  • 在你做任何事情之前,了解准备好的语句和占位符值,因为这段代码中充满了SQL injection bugs
  • 如果要插入大量数据,可以考虑使用LOAD DATA INFILE
  • @tadman 感谢您的提示,将其合并到我的代码中。

标签: java mysql sql performance mariadb


【解决方案1】:

不要简单地使用INSERT ...,而是使用

INSERT IGNORE ...

并且有一个UNIQUE(或PRIMARY)可以捕获“重复”。

INSERTing 一次插入一行的速度大约是一次插入 100 行的 10 倍。因此,如果您是通过代码生成它们,请执行

INSERT IGNORE INTO t
    (col1, col2, ...)
    VALUES
    (1,2,...),
    (22,55,...),
    ... ;

或者

LOAD DATA LOCAL INFILE '...' IGNORE ...

如果从文件中读取。

【讨论】:

    【解决方案2】:

    第一件事 - 不要为每个插入打开一个连接,除非您使用的是连接池。

    第二件事-使用PreparedStatement。这不仅可以使您免于 SQL 注入,还可以使其更快,因为它可以避免重复解析。

    第三件事 - 使用 PreparedStatement.addBatch() 并每 5000 行提交一批(或类似的东西)。这意味着您对所有插入使用相同的 Connection 和 PreparedStatement。

    第四件事 - 如果您只是用测试数据填充数据库并且您知道您的测试数据是唯一的,请在插入所有记录后创建索引。它会明显更快。

    第五件事 - 如果您使用 InnoDB,请确保您有足够的缓冲区空间来将整个索引保存在内存中,并将数据库放在 SSD 上(比 HDD 快约 30 倍)。

    如果您可以在 Java 之外执行此操作,则可以使用数据库的专有功能进行批量加载、从备份或快照恢复。检查您的数据库提供了哪些功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-04
      • 1970-01-01
      • 2019-04-18
      • 2010-09-05
      相关资源
      最近更新 更多