- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我目前正在开发用 java(7) 实现的桌面应用程序,该应用程序除其他外,还管理 sql 数据库中的大量数据记录。虽然只有几张表,但包含大量记录。我需要对单个表执行复杂的查询,但不需要复杂的联接操作。
到目前为止,我一直在使用 postgres。但由于它是一个桌面单用户应用程序,我还考虑使用 sqlite (不用说,这也会降低设置的复杂性)。所以我写了一个简单的python脚本来进行一些性能测试。让我惊讶的是,首先,sqlite 的实际执行情况如何,其次,在 python 中,查询响应时间比在 java 中小得多。
一个常见的场景是根据 id 列表选择一批记录。在python中,我使用以下代码来测试响应时间:
rand_selection = ','.join([str(int(random.random()* MAX_INDEX )) for i in xrange(PAGE_SIZE)])
start = time.time();
c = db.cursor();
res = c.execute("SELECT * FROM bigtable WHERE id in ("+rand_selection+")");
reslist = [str(t) for t in res]; c.close();
print( time.time() - start );
对于 MAX_INDEX=111000 和 PAGE_SIZE=100,这给出了大约 5 毫秒的增量。
嗯,太棒了。现在,让我们转向 java:我使用 jdbc-sqlite司机。我在同一个表上执行了完全相同的查询,查询时间始终在 200 毫秒左右,这对于我的用例来说是 Not Acceptable 。
我错过了什么吗?
我知道这是一个非常普遍的问题。但也许有人有一些 jdbc-sqlite 的经验,并且从经验中知道发生了什么......
[编辑]:按照建议使用 timit.default_timer() (感谢 Martijn Pieters)给了我类似的结果。
[Edit2]:根据 CL 的建议,我编写了 java 代码的简化版本。使用此代码,我无法验证结果,并且响应时间与 python 代码大致相同。但是,我在另一台机器上使用不同的 jdk(openjdk7 与 oracle jdk7)进行了测试。不可否认,我的其他测试代码很可能存在一些问题。
[编辑 2013-08-16]:我现在使用原始设置执行了相同的测试。我还将它与 postgres 进行了比较。
Model Name: MacBook Pro
Model Identifier: MacBookPro5,5
Processor Name: Intel Core 2 Duo
Processor Speed: 2.53 GHz
Memory: 8GB
OS-Version: 10.8.4
Java:
Java(TM) SE Runtime Environment (build 1.7.0_21-b12)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)
测试代码(请原谅草率的编码......):
package ch.dsd;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class Main {
private static int COL_COUNT = 20;
private static int TESTRUNS = 20;
private static int INDEX_COUNT = 64;
/*
CREATE TABLE bigtable ( id INTEGER PRIMARY KEY ASC, prop0 real, prop1 real, ... , prop19 real );
*/
static class Entity {
private long id;
private ArrayList<Double> properties = new ArrayList<Double>(COL_COUNT);
public Entity() {
for( int i = 0; i < COL_COUNT; i++) {
properties.add(0.0);
}
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public void setProperty(int idx, double prop) {
properties.set(idx, prop);
}
public double getProperty(int idx) {
return properties.get(idx);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for( double prop: properties ) {
sb.append(prop);
sb.append(",");
}
sb.delete(sb.length()-1, sb.length());
return sb.toString();
}
}
private static String placeholders( int n ) {
StringBuilder sb = new StringBuilder();
if( n > 0 ) {
sb.append("?");
for( int i = 1; i < n; i++ )
sb.append(",?");
return sb.toString();
}
return "";
}
private static void setRandomIdcs( PreparedStatement ps, int start, int stop, int max ) throws SQLException {
for( int i = start; i <= stop; i++ ) {
ps.setLong(i, (long) ((double) max * Math.random()));
}
}
private static void setRandomValues( PreparedStatement ps, int start, int stop ) throws SQLException {
for( int i = start; i <= stop; i++ ) {
ps.setDouble(i, Math.random());
}
}
private static void readFromResultSet( ResultSet rs, List<Entity> lst ) throws SQLException {
while(rs.next()) {
final Entity e = new Entity();
e.setId(rs.getLong(1));
for( int i = 0; i < COL_COUNT; i++ )
e.setProperty(i, rs.getDouble(i+2));
lst.add(e);
}
}
public static void performTest(Connection c) throws SQLException {
final PreparedStatement ps = c.prepareStatement("SELECT * FROM bigtable WHERE id in ("+placeholders(INDEX_COUNT)+")");
ArrayList<Entity> entities = new ArrayList<Entity>();
for( int i = 0; i < TESTRUNS; i++ ) {
setRandomIdcs( ps, 1, INDEX_COUNT, 1000000 ); // there are one million entries stored in the test table
long start = System.currentTimeMillis();
final ResultSet rs = ps.executeQuery();
readFromResultSet(rs, entities);
// System.out.println(entities.get(INDEX_COUNT-1));
System.out.println("Time used:" + (System.currentTimeMillis() - start));
System.out.println("Items read:" + entities.size());
rs.close();
entities.clear();
}
ps.close();
}
public static void createPSQLTable(Connection c) throws SQLException {
final String create_stmt = "CREATE TABLE IF NOT EXISTS bigtable (id SERIAL PRIMARY KEY, " +
"prop0 double precision,prop1 double precision,prop2 double precision,prop3 double precision,prop4 double precision,prop5 double precision,prop6 double precision,prop7 double precision,prop8 double precision,prop9 double precision,prop10 double precision,prop11 double precision,prop12 double precision,prop13 double precision,prop14 double precision,prop15 double precision,prop16 double precision,prop17 double precision,prop18 double precision,prop19 double precision)";
final PreparedStatement ps = c.prepareStatement(create_stmt);
ps.executeUpdate();
ps.close();
}
public static void loadPSQLTable( Connection c ) throws SQLException {
final String insert_stmt = "INSERT INTO bigtable VALUES (default, " + placeholders(20) + ")";
final PreparedStatement ps = c.prepareStatement(insert_stmt);
for( int i = 0; i < 1000000; i++ ) {
setRandomValues(ps, 1, 20);
ps.executeUpdate();
}
c.commit();
}
public static void main(String[] args) {
Connection c = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:/Users/dsd/tmp/sqlitetest/testdb.db");
c.setAutoCommit(false);
performTest(c);
c.close();
System.out.println("POSTGRES");
System.out.println("========");
final Properties props = new Properties();
props.setProperty("user", "dsd");
c = DriverManager.getConnection("jdbc:postgresql:testdb", props);
c.setAutoCommit(false);
createPSQLTable(c);
// loadPSQLTable(c);
performTest(c);
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
}
}
结果:
Time used:348
Items read:64
Time used:407
Items read:64
Time used:259
Items read:64
Time used:341
Items read:64
Time used:325
Items read:64
Time used:145
Items read:64
Time used:70
Items read:64
Time used:98
Items read:64
Time used:91
Items read:64
Time used:134
Items read:64
Time used:68
Items read:64
Time used:51
Items read:64
Time used:51
Items read:64
Time used:51
Items read:64
Time used:55
Items read:64
Time used:67
Items read:64
Time used:56
Items read:64
Time used:90
Items read:64
Time used:56
Items read:64
Time used:51
Items read:64
POSTGRES
========
Time used:75
Items read:64
Time used:58
Items read:64
Time used:31
Items read:64
Time used:26
Items read:64
Time used:34
Items read:64
Time used:6
Items read:64
Time used:5
Items read:64
Time used:4
Items read:64
Time used:5
Items read:64
Time used:6
Items read:64
Time used:5
Items read:64
Time used:6
Items read:64
Time used:4
Items read:64
Time used:28
Items read:64
Time used:3
Items read:64
Time used:4
Items read:64
Time used:4
Items read:64
Time used:4
Items read:64
Time used:3
Items read:64
Time used:5
Items read:64
最佳答案
Python 是用 C 语言编写的,并具有“sqlite”可执行文件,也是用 C 语言编写的,已链接。
没有数据编码,也没有格式之间的转换,因为 Python 和底层 sqlite 库都使用相同的数据类型和编码,这些数据类型和编码与编译它们的平台不同。
另一方面,Java(JVM 也是用 C 编写的,但是......)使用特定平台独立的数据类型,特别是所有字符串都是 unicode。为了与底层 sqlite 可执行文件进行通信,java 库必须使用 JNI,这(通常)涉及数据类型和字符编码的一些转换。这可能会非常消耗 CPU 资源,特别是在将 C 字符串转换为 unicode 并再次转换回来时。话虽如此,我经常使用 sqliteJDBC jar,但从未真正注意到任何性能问题。
您可以尝试将 JavaDB(又名 Derby)视为嵌入式 Java 数据库。它是用纯 Java 编写的,使用“ native ”java 编码并且是“零维护”。
关于java - SQLite:java/jdbc-sqlite 和 python/sqlite3 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18234431/
我一直在使用 Databricks JDBC 驱动程序版本 2.6.22,并尝试升级到 2.6.27。但是,升级后我收到消息说我的 JDBC URL 在尝试连接时无效。这些 JDBC URL 与旧版本
似乎JDBC Spec没有详细说明数据源连接池中alive or idle connections的准确含义。它只是具体实现吗? DBCP2如何或 HikariCP实际检查连接状态? 下面没有事件事务
在“XPages 扩展库”一书中,第 12 章,第 409 页有一个 JDBC 连接文件的例子: org.apache.derby.jdbc.EmbeddedDriver jdbc:
谁能告诉我 jdbc 是如何工作的?它如何设法与 DBMS 通信?因为 DBMS 可能是用其他编程语言编写的。 最佳答案 与数据库的通信由 JDBC 驱动程序处理,这些驱动程序可以使用各种策略与数据库
我想知道是否有人可以帮助我解决这个问题。我在尝试使用 Spring JDBC 编写代码时遇到了一个问题。当我运行服务器时,我收到了标题中提到的消息。我google了一下,有人说你应该导入ojdbc.j
我只是想运行一个示例 hivejdbc 客户端程序,但它给我一个内存不足的错误。 import java.sql.SQLException; import java.sql.Connection; i
我需要将 Google Spreadsheet 与 JasperReports Server 一起使用,为此我需要一个用于 Google Spreadsheet 的 JDBC 连接器。 我找到了这个
我需要将大量行(最多 100,000 行)插入到 6 个不同的 DB2 表中。我正在使用 Java JDBC 来完成它。我想在单个数据库事务中完成所有操作,以便在遇到任何问题时可以回滚整个操作。在某处
再次为自己是 Jmeter 新手道歉——我对 JDBC 请求有点困惑——我在过去的 3 个小时里浏览了这个网站上的帖子——但我找不到任何相关的东西(除非我我错过了一些东西)。 我的环境:Jmeter
我们正在创建一个带有 MySQL 后端的 XPages 应用程序。应用程序将被多个客户使用。每个都有自己的 NSF 数据库和相应的 MySQL 数据库。每个客户都有自己的 MySQL 用户名。我们正在
昨天我遇到了一个大问题。在我当前的项目中,我使用 Oracle 的 JDBC 的 ojdbc6 实现进行连接,但我还需要处理例如 oracle 8 数据库,这对于这个 JAR 是完全不可能的。 你会说
这个问题在这里已经有了答案: Closing JDBC Connections in Pool (3 个答案) 关闭 2 年前。 假设我有以下代码 DataSource source = (Data
我有 Informix 数据库,时间戳字段定义为 YEAR TO SECOND。 当我使用 JDBC rs.getString(column) 显示此字段时,它使用带毫秒的格式,因此此字段如下所示:
看完本教程之后; https://www.youtube.com/watch?v=ZnI_rlrei1s 我正在尝试使用logstash和jdbc获取我的本地主机mysql(使用laravel val
有人给我小费。 { "type": "jdbc", "jdbc": { "driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver"
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我正在尝试从mysql表中将1600万个文档(47gb)索引为elasticsearch索引。我正在使用jparante's elasticsearch jdbc river执行此操作。但是,在创建河
我正在尝试使用JDBC河将我的MySQL数据库复制到我的ElasticSearch索引中。 但是,每当我启动服务器时,与MySQL表的count(*)相比,创建的文档数量就增加了一倍。我通过清空索引并
使用新的logstash jdbc 连接器: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html后续的
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我是一名优秀的程序员,十分优秀!