2

我正在使用 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);

除了处理数组的行之外,一切都正常运行。对象 outputnodes 是一个 <5x23> 双矩阵,所以我试图将第一个 <1x23> 放入我的表中。

我已经为'"float8"'createArrayof 调用的一部分尝试了几种不同的名称和引号组合,但我总是得到这个错误:

??? 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,:)));
4

2 回答 2

5

用于数组的 JDBC 连接器的性能

我想指出,在您必须导出包含数组的大量数据的情况下,JDBC 可能不是最佳选择。org.postgresql.jdbc.PgArray首先,由于将原生 Matlab 数组转换为对象所导致的开销,它的性能会下降。其次,这可能会导致 Java 堆内存不足(而简单地增加 Java 堆内存大小可能不是灵丹妙药)。这两点都可以在下图中看到,该图片说明了datainsert来自 Matlab 数据库工具箱的方法的性能(它完全通过直接 JDBC 连接与 PostgreSQL 一起工作):

阵列的性能

蓝色图表显示batchParamExec来自 PgMex 库的命令的性能(有关详细信息,请参阅https://pgmex.alliedtesting.com/#batchparamexec)。datainsert红色图的端点对应于一定的最大数据量,没有任何错误地传入数据库。大于该最大值的数据量会导致“Java 堆内存不足”问题(Java 堆大小在图的顶部指定)。有关实验的更多详细信息,请参阅以下 论文,其中包含数据插入的完整基准测试结果

示例重做

可以看出,基于 libpq(PostgreSQL 的官方 C 应用程序程序员接口)的PgMex具有更高的性能,并且能够处理至少超过 2Gb 的卷。使用这个库,您的代码可以重写如下(我们在下面假设所有由<>符号标记的参数都已正确填充,该表neuron已经存在于数据库中并且具有字段classifier_idof int4thresholdof float8weightsoffloat8[]neuron_numof int4,最后,变量classfierIdVec, output_thresholds,outputnodesneuronNumVec已经定义并且是下面代码中的注释中显示的大小的数字数组;如果表字段的类型不同,则需要适当修复代码的最后一条命令):

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

需要注意的是,outputnodes不需要沿单独阵列上的行切割,因为后者具有相同的长度。对于具有不同大小的不同元组的数组,有必要将它们作为列单元数组传递,每个单元包含每个元组的自己的数组。

编辑:目前PgMex有免费的学术许可。

于 2017-07-24T12:55:27.847 回答
1

我对所有使用双引号的文档感到困惑,这是 Matlab 不允许的,仅使用单引号实际上解决了这个问题。正确的行是:

statementObject.setArray(3,dbHandle.createArrayOf('float8',outputnodes(1,:)));

代替

 statementObject.setArray(3,dbHandle.createArrayOf('"float8"',outputnodes(1,:)));

我最初认为问题在于我用于双精度的别名不正确,但正如 Craig 在上面的评论中指出的那样,情况并非如此。

于 2013-08-20T17:07:53.853 回答