【发布时间】:2013-12-06 10:24:46
【问题描述】:
我正在使用纬度和经度作为索引,并将 r*tree 模块编译到 sqlite3 数据库中以提高性能。此外,我将表加载到内存数据库中。令人惊讶的结果是,如果数据来自硬盘,ResultSet next 方法会减慢到 25-30 毫秒而不是 1 毫秒。通常我希望结果集有 250 个条目。
首先建立到内存的连接。
Class.forName("org.sqlite.JDBC");
Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:");
然后将表从硬盘复制到内存中:
Statement s = connection.createStatement();
s.execute("ATTACH 'myDB.db' AS fs");
s.executeUpdate("CREATE VIRTUAL TABLE coordinates USING rtree(id, min_longitude, max_longitude, min_latitude, max_latitude)");
s.executeUpdate("INSERT INTO coordinates (id, min_longitude, max_longitude, min_latitude, max_latitude)
SELECT id, min_longitude, max_longitude, min_latitude, max_latitude FROM fs.coordinates");
s.executeUpdate("CREATE TABLE locations AS SELECT * from fs.locations");
s.execute("DETACH DATABASE fs");
最后一步是查询数据库并将结果复制到一个对象中。
final String sql = "SELECT * FROM locations, coordinates WHERE (locations.id = coordinates.id) AND ((min_latitude >= ? AND max_latitude <= ?) AND (min_longitude >= ? AND max_longitude <= ?))";
PreparedStatement ps = connection.prepareStatement(sql);
// calculate bounding rec and fullfil sql statement.
Result rs = ps.executeQuery();
while (rs.next()) {
// copy the stuff here
}
我尝试了一些东西,例如连接应该是“只读”或使用 TYPE_FORWARD_ONLY 和 CONCUR_READ_ONLY 或增加获取大小来执行结果集,但 rs.next() 保持不变。
有没有人知道内存中发生了什么以及为什么rs.next() 这么慢?如何增加查询?
系统使用来自org.xerial和tomcat6的驱动sqlite-jdbc 3.7.2。
更新:添加了数据库架构
CREATE VIRTUAL TABLE coordinates USING rtree(
id,
min_latitude,
max_latitude,
min_longitude,
max_longitude);
CREATE TABLE locations(
id INTEGER UNIQUE NOT NULL,
number_of_locations INTEGER DEFAULT 1,
city_en TEXT DEFAULT NULL,
zip TEXT DEFAULT NULL,
street TEXT DEFAULT NULL,
number TEXT DEFAULT NULL,
loc_email TEXT DEFAULT NULL,
loc_phone TEXT DEFAULT NULL,
loc_fax TEXT DEFAULT NULL,
loc_url TEXT DEFAULT NULL);
【问题讨论】:
-
显示原始数据库的数据库架构,包括约束和索引。
-
我想知道您关于索引的问题。我的理解是 (min_latitude, max_latitude, min_longitude, max_longitude) 是一个新的二维索引,应该可以提高速度。 id 是两个表之间的链接。
标签: java database sqlite database-performance