【问题标题】:How to improve speed of SQLite updating如何提高 SQLite 更新速度
【发布时间】:2020-05-02 18:10:18
【问题描述】:

我正在编写一个不和谐的机器人,它会更新人们的余额,人们每发送一条消息都会获得一些金钱奖励。

我为此使用了一个 SQLite 数据库。 我测试了使用队列插入大量条目的情况,最终每个更新请求花费约 6.5 毫秒,其中 5.5 毫秒用于更新查询本身,剩余的 1 毫秒用于检查数据库,如果用户使用条目存在并构建查询字符串。

更新查询是以下几行:(最上面一行是查询)

  UPDATE exp12345678 SET exp = 68 , dummy = 159 WHERE userid = 54004700
  PreparedStatement pstmt = conn.prepareStatement(query);
   pstmt.executeUpdate();

插入查询属于(最上面一行是 sql 字符串)。

INSERT INTO exp12345678(userid, exp, dummy) VALUES(?,?,?)
PreparedStatement pstmt = conn.prepareStatement(sql);
                for (int i = 1; i <= args.length; i++) {
                    pstmt.setLong(i, mutationValues[i - 1]);
                }
                pstmt.executeUpdate();

我尝试使用具有多个线程的队列系统,根据用户使用的 id 在线程中拆分用户(如果我使用 2 个线程,我会将用户 id 编号查询传播到线程 1,同时传播偶数用户 id对线程 2 的数量查询)。这并没有缓解问题。

我不确定如何解决这个问题。我正在使用 SQLite。

更多详情: 查询是一次完成的,这是需要的,因为如果用户请求提供一些价值,他们需要知道他们当前的余额是否足够。

编辑:我使用这些 SQL 调用来创建表:

CREATE TABLE IF NOT EXISTS exp12345678 (
 id integer PRIMARY KEY,
 userid bigint,
 exp bigint,
 dummy bigint
);

这些用于从用户那里获取值(以创建更新查询)。

SELECT * FROM exp12345678 WHERE userid = 10437023

现在我所做的只是尝试向现有用户添加一个突变。有没有更快的方法来实现这一点?

【问题讨论】:

    标签: java sql database sqlite


    【解决方案1】:

    我不太遵守您一次只做一个记录的限制,所以这可能没有帮助,但一次执行一个更新往往会很慢。 JDBC 批量插入可能会对执行多个查询所需的时间产生巨大影响。以下是基于您的代码的示例。

    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
    
            int rowCount = 0;
            for (long mutationValue : mutationValues) {
                pstmt.setLong(i, mutationValue);
                pstmt.addBatch();
                rowCount++;
                if (rowCount % BATCH_SIZE == 0) { // You may have to do some experimentation to find a good value.
                    pstmt.executeBatch();
                }
            }
            if (rowCount % BATCH_SIZE != 0) {
                pstmt.executeBatch();
            }
        }
    

    【讨论】:

    • 我的朋友在您发送此邮件前几分钟发送了此邮件,真是巧合!无论如何,谢谢,这确实解决了问题,我现在的速度非常快。
    【解决方案2】:

    您正在检查用户是否存在 (SELECT),然后您正在插入 (INSERT) 或更新它 (UPDATE)。

    SELECTUPDATE 可以极大地受益于索引:

    create index ix1 on exp12345678 (userid);
    

    创建索引后再次测量时间。

    【讨论】:

    • 您能否详细说明这意味着什么?如,这一行如何在 SQL 数据库上执行更新?
    • 这是一个索引创建。您只需要运行一次,而不是每次更新。当您在 SELECT 和 UPDATE 上使用 WHERE userid = &lt;number&gt; 之类的条件时,该索引可以让 SQLite 快速找到一行。
    • 我按照您的建议执行了该行,但没有任何改变。有关更多信息,我将发布创建表字符串和选择字符串,也许那里有一些信息可以解释为什么它不起作用。如果不存在则创建表 exp12345678 (id integer PRIMARY KEY, userid bigint, exp bigint, dummy bigint); SELECT * FROM exp12345678 WHERE userid = 10437023
    • 为了清楚起见,我在最初的帖子中编辑了这些查询
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 2015-12-20
    相关资源
    最近更新 更多