java - 与 Firefox 数据库管理器相比,JDBC SELECT 非常慢

标签 java sql sqlite jdbc

已解决,当然在这里发布后它击中了我...现在使用来自 http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC#Download 的不同驱动程序不需要大量配置。

休息下方的原始问题。


我正在使用包含 OpenStreetMap 数据的 SQLite 数据库,并且在使用 JDBC 时遇到了一些问题。

下面的查询是我想用来快速获取接近用户位置的位置的查询(数字来 self 的测试数据,并由 java 代码添加)。

SELECT roads.nodeID, lat, lon 
FROM roads 
INNER JOIN nodes 
ON roads.nodeID=nodes.nodeID 
ORDER BY (ABS(lat - (12.598418)) + ABS(lon - (-70.043514))) ASC 
LIMIT 1

“道路”和“节点”都包含大约 130,000 行。

这个特定的查询是最密集的查询之一,它只使用了两次,所以应该可以满足我的需要。使用 Firefox SQLite 时,它​​的执行时间约为 281 毫秒,但在使用 sqlitejdbc-v056 的 Java 中,它需要 12 到 14 秒(处理器满负载)。

关于如何解决这个问题的任何线索?

public Node getNodeClosestToLocation(Location loc){
        try {
            Class.forName("org.sqlite.JDBC");
            Statement stat = conn.createStatement();
            String q = "SELECT roads.nodeID, lat, lon "+
            "FROM roads "+
            "INNER JOIN nodes "+
            "ON roads.nodeID=nodes.nodeID "+
            "ORDER BY (ABS(lat - ("+loc.getLat()+")) +
            ABS(lon - ("+loc.getLon()+"))) ASC "+
            "LIMIT 1";
            long start = System.currentTimeMillis();
            System.out.println(q);

            rs = stat.executeQuery(q);
            if(rs.next()) {
                System.out.println("Done. " + (System.currentTimeMillis() - start));

                return new Node(rs.getInt("nodeID"), rs.getFloat("lat"), rs.getFloat("lon"));
            }   

        }
        catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

最佳答案

当谈到 JDBC 中的 select 语句查询时,如果使用不当,它们可能会非常缓慢。几点:

  1. 确保为表格中的正确列编制索引。一个简单的行,例如:

Statement stat = connection.createStatement();<br/> stat.executeUpdate("create index {index_name} on orders({column_name});");<br/> stat.close();

创建索引:http://www.w3schools.com/sql/sql_create_index.asp

  1. 插入索引需要更长的时间,因为每个先前的索引都需要在插入新记录时更新。最好在执行完所有插入语句后创建索引(更好的性能)。索引列会影响插入性能,但选择性能要快得多。

  2. 更改 JDBC 驱动程序可能会略有帮助,但总的来说应该不是根本问题。还要确保您在 native 模式下运行。纯 Java 模式要慢得多,至少从我注意到的情况来看是这样。假设您使用的是 SQLite JDBC,以下代码段将告诉您正在运行的模式。

System.out.println(String.format("%s mode", SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java"));

我在拥有超过 50 万条记录的数据库中遇到缓慢选择的相同问题。如果我没有编制索引,我的应用程序的运行时间将是 9.9 天。现在,做完全相同的事情只需 2 分钟。当使用适当和优化的 sql 时,SQLite 非常快。

关于java - 与 Firefox 数据库管理器相比,JDBC SELECT 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9979891/

相关文章:

java - 比较通过套接字 UTF8 传递的字符串

java - Android 6.0 广播接收器不接收 BOOT_COMPLETE

mysql - Rails 中不区分大小写的 group_by?

android - 跨多个 Android 应用程序共享单个 SQLite 数据库。

java - 如何在 java 8 中使用带有 null 和空检查的平面图合并多个列表?

sql - 获取sql server中的行数,包括列值

mysql - MySQL 中的循环选择

mysql - SQL 连接多次?

SQLSTATE[HY000] : General error: 1 no such table

java - 定义包含 main() 方法的同一类的实例变量时出现 StackOverflowError