2012-04-02 59 views
4

解決,當然在發佈後它打我...現在使用不同的驅動程序從http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC#Download不需要廣泛的配置。JDBC SELECT與Firefox DB管理器相比非常緩慢

原始問題在休息之下。


我用含OpenStreetMap的數據SQLite數據庫打打鬧鬧,和我遇到一些麻煩JDBC。

下面的查詢是我想用來獲取位置接近我的用戶quicky位置(數字是從我的測試數據,並由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行。

這個特定的查詢是最密集的buyt之一,它只用了兩次,所以應該可以滿足我的需求。它在使用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; 
    } 
+0

sqllite查詢如何與瀏覽器相關?那應用程序中可能還有其他組件嗎? – kosa 2012-04-02 16:15:56

+0

對不起,這只是爲了證明查詢本身不應該慢,因爲另一個應用(在這種情況下,用於Firefox瀏覽器的SQLite DB管理器插件)的速度要快得多。你可以看到我在做計時,這是一個非常'年輕'的項目,只有一個單線程運行。 – 2012-04-02 16:21:09

+0

你確定你使用相同數量的數據,相同的查詢和結果是一樣的嗎?並且都是從同一個內存存儲器讀取的 - RAM/HDD/SDD?如果您從RAM中讀取100行進行FF測試,而從HDD讀取100行數據,則不會有任何疑問:)否則,這可能是Java實施中的一個錯誤 – Aprillion 2012-04-02 16:38:31

回答

0

使用PreparedStatement可能會給你稍微好一點的表現,但這裏沒有描述的幅度。

也許Firefox的SQLite正在使用一些提示。您可以嘗試獲取執行計劃以查看查詢在哪裏進行艱苦的工作,並根據需要創建一些索引。

您是否嘗試過記錄任何時間信息以確保它沒有獲得昂貴的連接?

1

當談到在JDBC中選擇語句查詢時,如果他們使用不正確,他們可能會非常痛苦地慢。幾點:

  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"));

我經歷了緩慢的選擇,同樣的問題在數據庫中有超過50萬分的記錄。如果我沒有索引,我的應用程序的運行時間應該是9.9天。現在這是一個快速的2分鐘做同樣的事情。當使用正確和優化的SQL時,SQLite速度非常快。