我已尝试使用pgmex。不幸的是它不适用于libpq5(matlab立即崩溃)。
答案 0 :(得分:13)
要在没有数据库工具箱的情况下从matlab连接到postgres,请执行以下操作:
% Add jar file to classpath (ensure it is present in your current dir)
javaclasspath('postgresql-9.0-801.jdbc4.jar');
% Username and password you chose when installing postgres
props=java.util.Properties;
props.setProperty('user', '<your_postgres_username>');
props.setProperty('password', '<your_postgres_password>');
% Create the database connection (port 5432 is the default postgres chooses
% on installation)
driver=org.postgresql.Driver;
url = 'jdbc:postgresql://<yourhost>:<yourport>\<yourdb>';
conn=driver.connect(url, props);
% A test query
sql='select * from <table>'; % Gets all records
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
% Read the results into an array of result structs
count=0;
result=struct;
while rs.next()
count=count+1;
result(count).var1=char(rs.getString(2));
result(count).var2=char(rs.getString(3));
...
end
答案 1 :(得分:6)
作为一般解决方案,您可以直接使用JDBC。 Modern Matlabs都嵌入了JVM。在Matlab中的Java CLASSPATH上获取Postgresql JDBC驱动程序JAR文件,您可以构造JDBC连接和语句对象。请参阅“help javaclasspath”。
有几个陷阱。在Matlab中动态类路径上从JAR自动注册JDBC驱动程序类似乎有点古怪,可能是因为它使用单独的URL类加载器而核心JDBC类在系统类加载器中。因此,您可能需要显式构造JDBC驱动程序类的实例并将它们传递给JDBC方法,而不是使用您在所有JDBC教程中看到的隐式驱动程序构造。此外,使用Matlab进行的每个Java方法调用都会产生性能开销,如果您在Matlab代码中循环结果集游标,则会变得昂贵。在Java中编写一个薄的包装层是值得的,它将JDBC的迭代接口包装在面向块的Matlab风格的接口中,读取结果集并在Java中用数组缓冲它们,并将整个数组传递回Matlab。
您也可以使用ODBC,但这需要编写与ODBC链接或使用ADO的MEX文件。更难和更便携。
编辑:如果使用自定义classpath.txt在静态Java类路径上获取JAR,则可以使自动驱动程序注册工作正常工作。答案 2 :(得分:6)
首先,问题本身顶部的链接已经破裂。据我所知,不再支持这个旧的pgmex库。但是有一个全新的高性能PostgreSQL客户端库PgMex 用C语言编写100%并与最新的PostgreSQL 9.6 libpq链接。
正如已经指出的那样,你可以直接使用JDBC,但恕我直言,至少可以使用一种可用的方法来加速查询的执行。例如,您可以应用在Undocumented Matlab网站上发表的一篇有趣的文章“加速Matlab-JDBC SQL查询”中描述的内容。 PostgreSQL JDBC驱动程序性能下降的主要原因是与本机Matlab格式(Java对象到Matlab,反之亦然)的重要数据转换开销。
但是JDBC本身具有某些限制,这些限制无法针对基本上大的数据集进行解决。例如,如果你必须处理数组,就可以很容易地看到它。让我们看一下下表,比较Matlab数据库工具箱中的datainsert
方法的数据插入性能(使用PostgreSQL,即通过直接JDBC连接,以便它可以被视为基于JDBC的连接器的相关代表)对于数组的情况,使用来自上述PgMex的batchParamExec
之一:
+-----------+-----------+--------------+------------------+ | Number of | Data size | Time for | Time for | | tuples | | datainsert | batchParamExec | | | | (sec.) | (sec.) | +-----------+-----------+--------------+------------------+ | 20000 | 23Mb | 37.0255 | 1.1217 | +-----------+-----------+--------------+------------------+ | 40000 | 46Mb | 72.4008 | 2.2669 | +-----------+-----------+--------------+------------------+ | 60000 | 69Mb | 112.4428 | 3.2055 | +-----------+-----------+--------------+------------------+ | 80000 | 92Mb | n/a | 4.2073 | +-----------+-----------+--------------+------------------+ | 100000 | 115Mb | n/a | 5.5277 | +-----------+-----------+--------------+------------------+ | 300000 | 346Mb | n/a | 14.3530 | +-----------+-----------+--------------+------------------+ | 600000 | 691Mb | n/a | 28.3156 | +-----------+-----------+--------------+------------------+ | 800000 | 922Mb | n/a | 38.2579 | +-----------+-----------+--------------+------------------+ | 1000000 | 1152Mb | n/a | 47.8714 | +-----------+-----------+--------------+------------------+ | 1200000 | 1382Mb | n/a | 56.6258 | +-----------+-----------+--------------+------------------+ | 1400000 | 1613Mb | n/a | 65.9764 | +-----------+-----------+--------------+------------------+ | 1750000 | 2016Mb | n/a | 82.1829 | +-----------+-----------+--------------+------------------+ | 2000000 | 2304Mb | n/a | 93.5854 | +-----------+-----------+--------------+------------------+
这里n/a
对应于给定插入方法导致“Java堆外存”问题的数据卷,所有这些实验的Java堆大小等于939Mb。有关以图形形式呈现的这些和其他实验的结果以及实验的更多详细信息,请参阅以下内容
"Performance comparison of PostgreSQL connectors in Matlab" article)。
因此,如果您必须处理具有简单标量类型且数量不是很大的数据,JDBC可能会完全满足您的需求。然而在其他方面
使用像上面提到的PgMex这样的基于libpq的解决方案是更好的恕我直言。除了PgMex之外,还有例如
一个用C ++编写的开源软件包mexPostgres(你可以在Matlab Central网站上找到它)。这个库
基于文本表示(来自libpq的PQgetvalue
函数)解析数据,并且只针对非常有限的数据类型列表
(事实上,它们是标量数字和逻辑,时间,日期,时间戳和间隔以及字符串,更复杂的类型,如数组再次超出范围)。但是通过文本表示传输非常慢,并且可以仅用于非常大的数据集。与PgMex有什么关系,这个库在Matlab和PostgreSQL之间实现了一个非常有效的二进制数据传输通道,没有任何文本解析。此外,所有这些都是以Matlab友好和本地方式完成的(以矩阵的形式,
多维数组,结构和任意其他Matlab格式)。
让我们根据从上面的一个答案中获得的示例给出一个如何处理后一个库的提示,但是使用PgMex重写。也就是说,数据导入是通过以下代码实现的(我们假设在下面的代码中,所有由<>
标记的参数的值都被正确填充,并且相应的表已经存在于数据库中):
% Create the database connection
dbConn=com.allied.pgmex.pgmexec('connect',[...
'host=<yourhost> dbname=<yourdb> port=<yourport> '...
'user=<your_postgres_username> password=<your_postgres_password>']);
% A test query
sql='select * from <table>'; % Gets all records
pgResult=com.allied.pgmex.pgmexec('exec',dbConn,sql); % Perform this test query
% Read the results
nFields=com.allied.pgmex.pgmexec('nFields',pgResult);
outCVec=cell(nFields,1);
fieldSpecStr='%<field_type_1> %<field_type_2> ...';
inpCVec=num2cell(0:nFields-1);
[outCVec{:}]=com.allied.pgmex.pgmexec('getf',pgResult,...
fieldSpecStr,inpCVec{:});
请参阅PgMex网站上的“getf”文档,了解有关其输入格式的详细信息
和输出参数(包括fieldSpecStr
)。 outCVec
的每个元素
包含具有字段valueVec
,isNullVec
和isValueNullVec
的结构。所有这些字段都有一个大小
沿着第一个维度与重新获得的元组数量一致,valueVec
包含的值
相应的表字段,而isNullVec
和isValueNullVec
是NULL的指示符。
答案 3 :(得分:1)
使用带有SSL模式的matlab连接到pgsql数据库时遇到问题。使用数据库工具箱它应该是这样的: conn =数据库(&#39; dbname&#39;,&#39;用户名&#39;,&#39;密码&#39;,&#39; org.postgresql.Driver&#39;,&#39; jdbc:的PostgreSQL:databaseURL:DBNAME:SSL =真安培; sslfactory = org.postgresql.ssl.NonValidatingFactory&安培;&#39)
但我有错误: &#39;致命:用户&#34;用户名&#34;&#39;
的密码验证失败所以我使用你的脚本并得到同样的错误。
我不得不添加一行
props.setProperty(&#39; SSL&#39;&#39;真&#39);
和正常的网址,而不是sslfactory ...如matlab帮助中所述。
所以它很好,但是我不能使用数据库工具箱的功能......好吧,这不是什么大问题!
我花了一些时间才发现这一点,所以也许知道如果他们在SSL模式下连接到远程数据库时也遇到问题可能会有用。
谢谢!
答案 4 :(得分:0)
MYSQL (additional link)会为你工作,至少作为起点吗?
答案 5 :(得分:0)
(免责声明:需要数据库工具箱)
以下是来自matlab脚本的ready setup postgresql server的完整示例,相应地调整数据库参数:
%Set preferences with setdbprefs.
setdbprefs('DataReturnFormat', 'cellarray');
setdbprefs('NullNumberRead', 'NaN');
setdbprefs('NullStringRead', 'null');
%Make connection to database.
%Using JDBC driver.
conn = database('mydb', 'USERNAME', 'YOURPASSWORD', 'Vendor',...
'POSTGRESQL', 'Server', 'SERVERIP', 'PortNumber', 5432);
%Read data from database, just an example on weather table in mydb database
curs = exec(conn, ['SELECT weather.city'...
' , weather.temperature'...
' FROM "mydb"."public".weather ']);
curs = fetch(curs);
close(curs);
%Assign data to output variable
untitled = curs.Data;
%Close database connection.
close(conn);
%Clear variables
clear curs conn
您的用户需要LOGIN权限角色,并且能够访问表格(GRANT)