【问题标题】:JDBC SELECT very slow in comparison to Firefox DB manager与 Firefox DB 管理器相比,JDBC SELECT 非常慢
【发布时间】:2012-04-16 07:37:32
【问题描述】:

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

休息下的原始问题。


我在处理一个包含 OpenStreetMap 数据的 SQLite 数据库,而我在使用 JDBC 时遇到了一些问题。

下面的查询是我想用来快速获取靠近我的用户位置的查询(数字来自我的测试数据,并由 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

'roads' 和 'nodes' 都包含大约 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;
    }

【问题讨论】:

  • sqllite查询怎么跟浏览器有关系?应用程序中的其他组件可以吗?
  • 抱歉造成混淆:这只是为了证明查询本身不应该很慢,因为另一个应用程序(在这种情况下是 Firefox 浏览器的 SQLite DB Manager 插件)做了很多快点。你可以看到我在做计时,这是一个非常“年轻”的项目,只有一个线程在运行。
  • 你确定你使用相同数量的数据,相同的查询并且结果相同吗?两者都是从同一个内存存储中读取的 - RAM / HDD / SDD?如果你从 RAM 中读取 100 行用于 FF 测试,从 HDD 中读取 130 000 行用于 Java,那就不足为奇了 :) 否则,这可能是 Java 实现中的一个错误
  • 为了比较,请尝试:SELECT (ABS(lat - (12.598418)) + ABS(lon - (-70.043514))) as distance, road.nodeID, lat, lon FROM road Roads.nodeID=nodes.nodeID ORDER BY 1 ASC LIMIT 1 上的 INNER JOIN 节点
  • 此外,如果您连续两次执行相同的查询,第二次执行会更快,因为服务器缓存了数据

标签: java sql sqlite jdbc


【解决方案1】:

使用PreparedStatement 可能会给您带来更好的性能,但没有此处描述的量级。

也许 Firefox SQLite 正在使用一些提示。您可以尝试获取执行计划以查看查询在哪里进行了艰苦的工作,并在需要时创建一些索引。

您是否尝试记录任何时间信息以确保它没有获得昂贵的连接?

【讨论】:

    【解决方案2】:

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

    1. 确保索引表中正确的列。简单的一行如:

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

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

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

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

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

    我在记录超过 500K 的数据库中选择缓慢时遇到了同样的问题。如果我没有编制索引,我的应用程序的运行时间将是 9.9 天。现在只需 2 分钟即可完成完全相同的操作。当使用适当和优化的 sql 时,SQLite 非常快。

    【讨论】:

      猜你喜欢
      • 2017-10-06
      • 2021-02-13
      • 2017-05-07
      • 1970-01-01
      • 2015-01-27
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多