我有一个应用程序会生成大量需要快速插入的数据(大约 1300 万条记录)。我使用 JPA 2.0/Hibernate 和 Postgres 9.1,我设法实现了相当好的性能(每秒大约 25k 个插入),通过多线程和每几千个左右插入批量插入,在大约 8 分钟内完成整个运行。
但是,我注意到我有一些缺少索引的外键,我真的希望从分析的角度深入了解数据,并删除特定运行的数据。不幸的是,当我将这 3 个索引添加到获得最多插入的表中时,性能急剧下降到每秒 3k 左右。
有什么办法可以避免这种性能下降?我知道一种选择是在运行之前删除索引并在最后重新创建它们。另一个更笨拙的选择是在文件中生成最大表的数据并使用COPY. 我想我只能在关系中最大的表上执行此操作,因为我需要知道外键值(通过序列生成)。
这两种选择似乎都是黑客。有没有其他解决方案,可能对应用程序的干扰少一点?一些设置告诉 postgres 推迟索引或类似的东西?
欢迎任何想法。
postgresql performance index java postgresql-9.1 performance-tuning
“消息”是指下图中的“消息”选项卡,其中包括“警告”、“受影响的 n 行”以及下图中的执行时间。在 JDBC 中,ResultSet 类用于检索“结果”。有没有办法通过JDBC获取“消息”选项卡中的所有信息?

我有 Oracle DB 11g 企业版,我想从我的 java 代码执行 sql 脚本。我正在从 .sql 文件中读取这个 sql 脚本,该脚本包含诸如create table, create type, alter table, drop type, 之类的语句drop procedure,insert into以及带有begin和end以及所有此类构造的pl/sql 块。
我的问题是,如何将单独的 sql 语句从 java 代码中分离出来执行?在 MS SQL 中,我可以简单地按GO关键字分隔这些 sql 语句,而在 Oracle db 中没有这样的分隔符。那么通常什么在 Oracle db 脚本中用作分隔符?
例如,我在我的 sql 脚本和其他 sql 语句中有以下创建触发器块。这里我有分号,我不能将其视为 SQL 语句终止符(PL/SQL 块本身可以包含多个分号分隔的语句)。这意味着我不能使用;类似于GO(在 MS SQL 中)。
CREATE OR REPLACE TRIGGER SQLVersionHistory_SeqNum_TRG
BEFORE INSERT
ON SQLVersionHistory
FOR …Run Code Online (Sandbox Code Playgroud) 我正在使用 ExecutorService,其固定线程池为 50,固定数据库连接池为 50,使用 HikariCP。每个工作线程处理一个数据包(一个“报告”),检查它是否有效(其中每个报告必须有唯一的unit_id、时间、纬度和经度),从连接池中抓取一个db连接,然后将报告插入报告表。唯一性约束是用 postgresql 创建的,称为“reports_uniqueness_index”。当我的音量很大时,我会收到大量以下错误:
org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint "reports_uniqueness_index"
Run Code Online (Sandbox Code Playgroud)
这就是我认为的问题所在。在插入数据库之前,我执行检查以确定表中是否已存在具有相同unit_id、时间、纬度和经度的报告。如果不是,那么报告是有效的,我执行插入。但是,我认为因为我使用并发,所以我有 50 个线程同时检查报告是否有效,并且由于尚未插入它们中的任何一个,每个线程都认为它具有有效的报告以及何时将它们插入同一时刻,也就是 postgresql 引发错误的时候。
我想要一个不会因并发而产生任何延迟的解决方案。我一直试图避免使用同步语句或重入锁,因为数据库插入需要尽快发生。这是这里的插入:
private boolean save(){
Connection conn=null;
Statement stmt=null;
int status=0;
DbConnectionPool dbPool = DbConnectionPool.getInstance();
String sql = = "INSERT INTO reports"
sql += " (unit_id, time, time_secs, latitude, longitude, speed, created_at)";
sql += " values (...)";
try {
conn = dbPool.getConnection();
stmt = conn.createStatement();
status = stmt.executeUpdate(sql);
} catch (SQLException e) {
return false;
} finally {
try { …Run Code Online (Sandbox Code Playgroud) 我使用 Java 中的以下代码创建并使用内存中的 H2 数据库(不写入存储)进行演示和快速测试:
Connection conn = DriverManager.getConnection( "jdbc:h2:mem:example_db" ) ;
Run Code Online (Sandbox Code Playgroud)
这第一次有效,但随后数据库似乎消失了,无法进行进一步的工作。如何随着时间的推移使用相同的内存数据库?
我们有一个 Sybase 数据库,当前在某些表中存储日期时间值。如果我们将装有 Sybase 数据库的服务器移动到位于另一个时区的另一个国家/地区,数据库中的日期时间值是否会以不同的方式表示?
换句话说,请考虑以下场景:
Sybase 数据库在时区 +2:00 运行。
从我位于时区 +1:00 的 Java 应用程序中,它将 1970 年 1 月 1 日 1:00 写入数据库,这是应用程序时区中的纪元 0。
preparedStatement.setTimestamp(3, new Timestamp(0));
Run Code Online (Sandbox Code Playgroud)
但是,当我使用 SQL Workbench/J 客户端(时区 +1:00)查询数据库时,我看到
1970-01-01 01:00:00
Run Code Online (Sandbox Code Playgroud)
在我的桌子上。事实上,无论我将计算机时钟更改为哪个时区,SQL Workbench/J 客户端始终1970-01-01 01:00:00从数据库中读取数据。
位于时区 +3:00 的另一个 Java 客户端读取的值与
1970-01-01 01:00:00
Run Code Online (Sandbox Code Playgroud)
翻译为纪元-7200000或-2:00客户的时区!
那么回到我原来的问题,Sybase 是否将日期时间值存储为字符串或纪元?我没有可以进行实验的免费 Sybase 服务器,那么当我们将服务器移动到另一个时区不同的国家/地区时,我们会发生什么情况呢?
我们使用的类型是“datetime”,例如:
CREATE TABLE "dbo"."whatever" (eventDate datetime NOT NULL);
Run Code Online (Sandbox Code Playgroud) 我有时间戳(存储为 BIGINT)格式,我无法变成人类可读的格式:
1462975819250
Run Code Online (Sandbox Code Playgroud)
它指向 2016 年 5 月 11 日的日期。但是函数 to_timestamp() 将其转换为:
48329-11-10 13:00:49.999872+01
Run Code Online (Sandbox Code Playgroud)
我想创建一个可以显示这些值的 VIEW,不知道要使用什么函数。
该字段由 Java 程序(我认为是 EclipseLink)编写。我没有程序的源代码。
我有一个带有 Oracle DB 的 Java webapp,我尝试在数据迁移脚本的末尾执行此语句:
EXEC DBMS_STATS.GATHER_TABLE_STATS (ownname => 'MY_SCHEMA', tabname => 'MY_TABLE', estimate_percent => dbms_stats.auto_sample_size);
Run Code Online (Sandbox Code Playgroud)
它适用于 sql*plus,但不适用于 JDBC:
"Error: ORA-00900: invalid SQL statement"
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
我的 Java 源代码有点卡在这里。首先我想从数据库中完全删除它,因为我想重新编译它,但我不能删除它,因为如果我执行这个命令:
drop java source "SCHEMA.JAVASOURCENAME";
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
ORA-04043: object JAVASOURCENAME does not exist
Run Code Online (Sandbox Code Playgroud)
Javasource 本身具有这种结构(这是它的 plsql/java 代码):
create or replace and compile java source named myjavasource as
import java.io.*;
import some.custom.jar.one.*;
import some.custom.jar.two.*;
import some.custom.jar.three.*;
public class MyJavaClass
{
public static String myjavafunction(String connectString, String identity, String password)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
我以 DBA 身份和我的用户执行了这个“创建或替换和编译 java 源代码...”命令,我不知道这是否可能是问题所在。
所以我的问题是,我怎样才能删除这个 java 源代码?
我的第二个问题是我可以处理自定义 jars 吗?我用这个命令导入了它们:
call dbms_java.loadjava('-genmissing -r -v -force -grant SCHEMA ./some.custom.jar.one.jar');
Run Code Online (Sandbox Code Playgroud)
我还以 DBA 身份和我的用户执行了此操作。如果是检查无效对象:
SELECT *
FROM user_objects
WHERE …Run Code Online (Sandbox Code Playgroud) 当您有一列bit数据类型时,在 Java POJO 将该表映射到使用javax.persistence注释的对象时,将使用什么 Class 来表示该列?
我试过了Boolean,没有用,并产生了以下错误:
org.hibernate.exception.SQLGrammarException: 无法插入: [com.DomainClassName]
java.sql.SQLException: '-' 附近的语法不正确。
编辑:Java 布尔值确实映射到 SQL Server 中的位数据类型。我有一个列名,里面有一个破折号,我必须更改。
我目前正在做一些休眠性能测试。我的要求是在包含 800 万行和 350 列的表的特定列中搜索数据。目前,我无法访问该数据库,但是,我现在使用的测试数据库也包含 8 百万+。
我的问题是,在包含 350 列的表中搜索数据与在包含 25 列的表中搜索数据时,在扫描速度方面是否存在显着差异?
顺便说一下,我检查数据的方式是:
sessionFactory.getCurrentSession().createSQLQuery("SELECT COL_5 from MY_TABLE where COL_5='" + theColValuePassedFromParameter+ "'").list();
Run Code Online (Sandbox Code Playgroud)
其中,如果返回的列表为空,布尔方法将返回true,否则返回false;如果有人能指出我在休眠中搜索非主键数据的更好、更高效的方法,我也将不胜感激。
提前致谢...
JDBC 4.3 更新随 Java 9 2017-10一起发布。它的几个变化之一是关于和方法发出信号\xe2\x80\xa6 的新功能ConnectionbeginRequestendRequest
\n\n\n向驱动程序提示一个请求(一个独立的工作单元)正在此连接上开始。每个请求都独立于客户端或服务器上连接的本地状态的所有其他请求。beginRequest、endRequest 对之间完成的工作不依赖于连接上完成的任何其他工作,无论是作为另一个请求的一部分还是在任何请求之外。一个请求可能包含多个事务。可能存在对已提交数据库状态的依赖性,因为它不是连接本地的。
\n
\xe2\x80\xa6 和 \xe2\x80\xa6
\n\n\n\n\n\xe2\x80\xa6 是可选的,特定于供应商的,并且应该在很大程度上是透明的。
\n
\xe2\x9e\xa0 请解释一下此功能的用途。
\n\n它似乎是关于比事务更大的事情,但与两阶段提交无关。与JDBC 4.3 的主要新特性sharding有关吗?
\n\n我并不是在询问这些数据库是否已针对 JDBC 4.3 更新了JDBC 驱动程序。我问的是更大的情况,在跨连接的数据库连接上下文中“请求”的含义和目的是什么。
\n\n奇怪的是,JDBC 4.3 规范只提到了这一点,没有任何解释:
\n\n\nJDBC API 更改
\n\n对现有 JDBC 接口进行了以下更改。
\n\n\n\n
java.sql.Connection添加了方法 …
我无法通过 jTDS 连接连接到我的 Microsoft SQL Server 数据库:
Connection conn = DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433
/MnA;instance=SQLEXPRESS", "sa","");
Run Code Online (Sandbox Code Playgroud)
SQL Server 已启用,TCP/IP 已启用,混合服务器身份验证已启用。
有任何想法吗?
java.sql.SQLException: Login failed for user 'sa'.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:368)
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2820)
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2258)
at net.sourceforge.jtds.jdbc.TdsCore.login(TdsCore.java:603)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.<init>(ConnectionJDBC2.java:345)
at net.sourceforge.jtds.jdbc.ConnectionJDBC3.<init>(ConnectionJDBC3.java:50)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at DB.dbConnect(testConnection.java:17)
at testConnection.main(testConnection.java:7)
Run Code Online (Sandbox Code Playgroud) java ×13
jdbc ×6
postgresql ×4
oracle ×3
performance ×2
plsql ×2
sql-server ×2
connections ×1
datetime ×1
h2 ×1
index ×1
sharding ×1
sybase ×1
timestamp ×1
timezone ×1