SQLite jdbc db 导致内存因大量输入而阻塞

问题描述 投票:0回答:0

我正在做一个小项目/测试,在那里我接受一个large文本输入并处理它以创建一个文本输出。 为此,我开始使用本地 SQLite db 和 JDBC lib(因为我在 Java 中这样做)。

问题是(出于某种原因)内存(RAM使用)随着输入的增加而不断增加,但是我需要程序使用非常有限的HEAP。

虽然该程序适用于我的测试用例,但它并没有以最佳方式运行,也就是说没有按预期运行。

上图不好的原因是因为我的数据库存储在本地,我只在需要时提取选定数量的 (100) 个数据库条目,所以无论出于何种原因,HEAP 或它的使用都应该增加。 我还想稍后添加线程以提高处理速度,因为当我从写入 RAM 切换到写入本地文件时,执行速度从 14 秒直线下降到 10 分钟。 班级: 主要 -> https://pastebin.com/rh27xsqr

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
public class Main {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"));
             Connection connection = DriverManager.getConnection("jdbc:sqlite:temp.db")) {
            Class.forName("org.sqlite.JDBC");
            Table table = new Table(connection);
            String line = reader.readLine();
            while (line != null) {
                String[] command = line.split(",");
                switch (command[0]) {
                    case "u":
                        int apples = Integer.parseInt(command[1]);
                        int size = Integer.parseInt(command[2]);
                        switch (command[3]) {
                            case "bid":
                                table.setBids(apples, size);
                                break;
                            case "ask":
                                table.setAsks(apples, size);
                                break;
                        }
                        break;
                    case "q":
                        String data = "";
                        switch (command[1]) {
                            case "best_bid":
                                data = table.getBestbid();
                                break;
                            case "best_ask":
                                data = table.getBestask();
                                break;
                            case "size":
                                data = table.getDesiredSize(Integer.parseInt(command[2]));
                                break;
                        }
 
                        if (!data.equals("")) {
                            writer.append(data).append("\n");
                        }
 
                        break;
 
                    case "o":
                        int size2 = Integer.parseInt(command[2]);
                        switch (command[1]) {
                            case "buy":
                                table.buy(size2);
                                break;
                            case "sell":
                                table.sell(size2);
                                break;
                        }
                        break;
                    default:
                        System.err.println("Error: unknown command - \"" + command[0] + "\"");
                        break;
                }
                line = reader.readLine();
            }
        } catch (IOException | SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

smalldb -> https://pastebin.com/PdkqgPZT

import java.sql.*;
import java.util.Collections;
import java.util.Objects;
import java.util.TreeMap;
 
public class Smalldb {
    private Connection connection;
    private PreparedStatement preparedStatement;
    private Statement statement;
    private ResultSet resultSet;
 
    public Smalldb(Connection connection) {
        try {
            this.connection = connection;
            //create db
            statement = connection.createStatement();
            statement.execute("CREATE TABLE IF NOT EXISTS asks (id INTEGER PRIMARY KEY, apples INT, amount INT)");
            statement.execute("CREATE TABLE IF NOT EXISTS bids (id INTEGER PRIMARY KEY, apples INT, amount INT)");
        } catch (SQLException e) {
            e.printStackTrace();
            throw new Error("Problem", e);
        }
    }
    public void updateAsks(int apples, int amount) throws SQLException {
        preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=?");
        preparedStatement.setInt(1, apples);
        resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) {
            preparedStatement = this.connection.prepareStatement("UPDATE asks SET amount=? WHERE apples = ?");
            preparedStatement.setInt(1, amount);
            preparedStatement.setInt(2, apples);
            preparedStatement.executeUpdate();
        } else {
            preparedStatement = this.connection.prepareStatement("INSERT INTO asks (apples, amount) VALUES (?, ?)");
            preparedStatement.setInt(1, apples);
            preparedStatement.setInt(2, amount);
            preparedStatement.executeUpdate();
        }
        resultSet.close();
        preparedStatement.close();
    }
 
    public void updateBids(int apples, int amount) throws SQLException {
        preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=?");
        preparedStatement.setInt(1, apples);
        resultSet = preparedStatement.executeQuery();
        if(resultSet.next()) {
            preparedStatement = this.connection.prepareStatement("UPDATE bids SET amount=? WHERE apples = ?");
            preparedStatement.setInt(1, amount);
            preparedStatement.setInt(2, apples);
            preparedStatement.executeUpdate();
        } else {
            preparedStatement = this.connection.prepareStatement("INSERT INTO bids (apples, amount) VALUES (?, ?)");
            preparedStatement.setInt(1, apples);
            preparedStatement.setInt(2, amount);
            preparedStatement.executeUpdate();
        }
        resultSet.close();
        preparedStatement.close();
    }
 
    public String getBestASK() throws SQLException {
        preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=(SELECT MIN(apples) FROM asks WHERE amount != 0)");
        resultSet = preparedStatement.executeQuery();
        resultSet.next();
        String best_ask = resultSet.getInt("apples") + "," + resultSet.getInt("amount");
        resultSet.close();
        preparedStatement.close();
        return best_ask;
    }
 
    public String getBestBID() throws SQLException {
        preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=(SELECT MAX(apples) FROM bids WHERE amount != 0)");
        resultSet = preparedStatement.executeQuery();
        resultSet.next();
        String best_bid = resultSet.getInt("apples") + "," + resultSet.getInt("amount");
        resultSet.close();
        preparedStatement.close();
        return best_bid;
    }
 
    public String getDesiredSize(int apples) throws SQLException {
        preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=?");
        preparedStatement.setInt(1, apples);
        resultSet = preparedStatement.executeQuery();
        if (!resultSet.next()) {
            preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=?");
            preparedStatement.setInt(1, apples);
            resultSet = preparedStatement.executeQuery();
            resultSet.next();
        }
        String desired_size = resultSet.getString("amount");
        resultSet.close();
        preparedStatement.close();
        return desired_size != null && !Objects.equals(desired_size, "") ? desired_size : "0";
    }
 
    public TreeMap<Integer, Integer> get100bestasks() throws SQLException {
        TreeMap<Integer, Integer> data = new TreeMap<>();
        statement = this.connection.createStatement();
        resultSet = statement.executeQuery("SELECT * FROM asks ORDER BY apples LIMIT 100");
        while (resultSet.next()) {
            int apples = resultSet.getInt("apples");
            int amount = resultSet.getInt("amount");
            data.put(apples, amount);
        }
        resultSet.close();
        statement.close();
        return data;
    }
 
    public TreeMap<Integer, Integer> get100bestbids() throws SQLException {
        TreeMap<Integer, Integer> data = new TreeMap<>(Collections.reverseOrder());
        statement = this.connection.createStatement();
        resultSet = statement.executeQuery("SELECT * FROM bids ORDER BY apples DESC LIMIT 100");
        while (resultSet.next()) {
            int apples = resultSet.getInt("apples");
            int amount = resultSet.getInt("amount");
            data.put(apples, amount);
        }
        resultSet.close();
        statement.close();
        return data;
    }
}

表 -> https://pastebin.com/Ytwn5raM

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.TreeMap;
 
public class Table {
    Smalldb db;
    private TreeMap<Integer, Integer> bids = new TreeMap<>(Collections.reverseOrder());
    private TreeMap<Integer, Integer> asks = new TreeMap<>();
    public Table(Connection connection) throws SQLException {
        this.db = new Smalldb(connection);
    }
    public void setBids(Integer apples, Integer amount) throws SQLException {
            this.db.updateBids(apples,amount);
    }
    public void setAsks(Integer apples, Integer amount) throws SQLException {
        this.db.updateAsks(apples,amount);
    }
    public void buy(Integer size) throws SQLException {
        int check=size;
        while(size>0){
            asks = db.get100bestasks();
            for (Integer key:this.asks.keySet()) {
                if (size<=0) break;
                Integer value = this.asks.get(key);
                if(value >=size) {
                    this.asks.replace(key, value-size);
                    db.updateAsks(key,value-size);
                }
                else if (value <size) {
                    this.asks.replace(key,0);
                    db.updateAsks(key,0);
                }
                size-=value;
            }//100 entries passed
            if(check==size || this.asks.size()<=100) size=0;//bad input checker
        }
    }
    public void sell(Integer size) throws SQLException {
        int check=size;
        while(size>0){
            bids = db.get100bestbids();
            for (Integer key:this.bids.keySet()) {
                if (size<=0) break;
                Integer value = this.bids.get(key);
                if(value >=size) {
                    this.bids.replace(key, value-size);
                    db.updateBids(key,value-size);
                }
                else if (value <size) {
                    this.bids.replace(key,0);
                    db.updateBids(key,0);
                }
                size-=value;
            }//100 entries passed
            if(check==size || this.bids.size()<=100) size=0;//bad input checker
        }
    }
    public String getBestbid() throws SQLException {
        String data;
        data=this.db.getBestBID();
        return data;
    }
 
    public String getBestask() throws SQLException {
        String data;
        data=this.db.getBestASK();
        return data;
    }
 
    public String getDesiredSize(Integer s) throws SQLException {
        return this.db.getDesiredSize(s);
    }
}

我还尝试了以下网站的解决方案:https://www.sqlite.org/inmemorydb.html

然而,这只会在内存中创建与我想要的相反的数据库。

感谢所有提示和答案。

java sqlite jdbc
© www.soinside.com 2019 - 2024. All rights reserved.