我正在使用JDBC通过Matlab访问postgresql数据库,并且在尝试插入我希望存储为数组而不是单个值的值数组时已经挂起。我正在使用的Matlab代码如下:
insertCommand = 'INSERT INTO neuron (classifier_id, threshold, weights, neuron_num) VALUES (?,?,?,?)';
statementObject = dbhandle.prepareStatement(insertCommand);
statementObject.setObject(1,1);
statementObject.setObject(2,output_thresholds(1));
statementObject.setArray(3,dbHandle.createArrayOf('"float8"',outputnodes(1,:)));
statementObject.setObject(4,1);
statementObject.execute;
close(statementObject);
除了处理数组的行外,一切都正常运行。对象输出节点是< 5x23>双矩阵,所以我试图把第一个< 1x23>进入我的桌子。
我为createArrayof调用的'"float8"'
部分尝试了几种不同的名称和引号组合,但我总是收到此错误:
??? Java exception occurred:
org.postgresql.util.PSQLException: Unable to find server array type for provided name "float8".
at org.postgresql.jdbc4.AbstractJdbc4Connection.createArrayOf(AbstractJdbc4Connection.java:82)
at org.postgresql.jdbc4.Jdbc4Connection.createArrayOf(Jdbc4Connection.java:19)
Error in ==> Databasetest at 22
statementObject.setArray(3,dbHandle.createArrayOf('"float8"',outputnodes(1,:)));
答案 0 :(得分:5)
我想要注意的是,在必须导出包含数组的大量数据的情况下,JDBC可能不是最佳选择。首先,由于将原生Matlab数组转换为org.postgresql.jdbc.PgArray
个对象而导致的开销,其性能下降。其次,这可能导致Java堆内存不足(并且简单地增加Java堆内存大小可能不是万能的)。这两点可以在下面的图片中看到,它说明了Matlab数据库工具箱中datainsert
方法的性能(它完全通过直接JDBC连接与PostgreSQL一起工作):
蓝色图表显示来自PgMex库的batchParamExec
命令的性能(有关详细信息,请参阅https://pgmex.alliedtesting.com/#batchparamexec)。红色图的端点对应
datainsert
传递到数据库的某个最大数据量没有任何错误。
大于该最大值的数据量会导致“Java堆内存不足”问题
(Java堆大小在图的顶部指定)。
有关实验的更多详细信息,请参阅以下内容
paper with full benchmarking results for data insertion
可以看出PgMex基于libpq(官方C应用程序程序员与PostgreSQL的接口)具有更高的性能,并且能够处理至少高达2Gb以上的卷。
使用这个库,您的代码可以按如下方式重写(我们假设下面所有标记为<>
符号的参数都已正确填充,表neuron
已经存在于数据库中且包含字段{{1} } classifier_id
,int4
threshold
,float8
weights
和float8[]
neuron_num
,最后,变量int4
,classfierIdVec
,output_thresholds
和outputnodes
已经定义,并且是下面代码中的注释中显示的数字数值数组;在表格字段类型的情况下是不同的你需要适当地修复代码的最后一个命令):
neuronNumVec
应该注意的是,% Create the database connection
dbConn = com.allied.pgmex.pgmexec('connect',[...
'host=<yourhost> dbname=<yourdb> port=<yourport> '...
'user=<your_postgres_username> password=<your_postgres_password>']);
insertCommand = ['INSERT INTO neuron '...
'(classifier_id, threshold, weights, neuron_num) VALUES ($1,$2,$3,$4)'];
SData = struct();
SData.classifier_id = classifierIdVec(:); % [nTuples x 1]
SData.threshold = output_thresholds(:); % [nTuples x 1]
SData.weights = outputnodes; % [nTuples x nWeights]
SData.neuron_num = neuronNumVec; % [nTuples x 1]
com.allied.pgmex.pgmexec('batchParamExec',dbConn,insertCommand,...
'%int4 %float8 %float8[] %int4',SData);
不需要沿着不同阵列上的行切割,因为后者是这样
长度相同。对于具有不同大小的不同元组的数组,必须通过它们
作为一个列单元格数组,每个单元格包含每个元组的自己的数组。
编辑:目前PgMex拥有免费的学术许可。
答案 1 :(得分:1)
我对所有使用双引号的文档感到困惑,Matlab不允许,只使用单引号实际解决了这个问题。正确的路线是:
statementObject.setArray(3,dbHandle.createArrayOf('float8',outputnodes(1,:)));
而不是
statementObject.setArray(3,dbHandle.createArrayOf('"float8"',outputnodes(1,:)));
我原本以为问题在于我用于双精度的别名是不正确的,但正如Craig在上面的评论中指出的那样情况并非如此。