有一段时间以来,我正在测试现有MS-Access数据库和MATLAB之间的连接。目前我有以下本地配置(同一本地驱动器上的MATLAB和DB):
MATLAB 2013a(32位)和MS Access 2007
在解决了MATLAB 64位的连接问题后,我转移到了32位,现在连接工作正常。连接通过数据库工具箱完成:
conn = database('Test_DB', '', '');
执行时间非常烦人。 我已经将MS Access中的执行时间(使用run!按钮直接在数据库中执行查询)与MATLAB执行查询所用的时间进行了比较,并使用fetch来获取数据。差异几乎是一个数量级。
通常,我有两个大表(表1 - 20列x 1' 000' 000行和表2 - 10列x 10&#39,000&#39,000行)。查询非常简单,根据所选日期组合两个表中的多个字段。 Inside Access(取决于版本2003或2007)大约需要7到10秒。当从Matlab执行时(SQL命令完全相同),它需要70到75秒。 我已经尝试了很多东西来理解这里的问题,但没有成功。如果有人知道类似的问题,我会很高兴有一些意见。
更具体一点:Matlab 32位ver。 2013a在64位Win 7,i7-3770与8GB RAM。对于数据库工具箱,我使用ODBC Microsoft Access驱动程序6.01.7601.17632,ODBCJT32.DLL日期为23.12.2011。
查询使用两个表T1和T2,如下所示:
strSQL = [ 'SELECT DISTINCT T1.TF1, T1.SI1, T1.SI2, T2.TF2, T1.DATE1 ' ...
'FROM T2 INNER JOIN T1 ' ...
'ON T2.TF1 = T1.TF1 ' ...
'WHERE (((T1.DATE1)=#', date1, '#));'];
TF1,TF2是文本字段
SI1,SI2是数字(简单)字段
DATE1是日期字段
T1有7,000,000行,2个文本字段,3个数字字段,1个日期字段
T2有13,000行,39个文本字段,12个数字字段,1个日期字段
答案 0 :(得分:0)
从Matlab运行它所花费的额外时间可能是将数据传输出Access引擎并将其转换为Matlab数据类型。那里存在相当大的阻抗不匹配,并且Matlab并不一定使用最有效的类型。
这听起来很慢,听起来你可能正在使用默认的cellarray
数据返回格式。这是一种不适合较大数据集的低效格式。 (或者,imho,很多东西。)它将所有列(包括数字)存储在一个二维单元阵列中。
使用structure
切换为table
或新的setbdprefs()
数据返回格式。这应该会给你一些加速和内存碎片的帮助。
setdbprefs('DataReturnFormat', 'table');
conn = database( ... )
(我不确定R2013a中是否有table
可用;它是新的。尝试一下,看看它是否有效;即使在R2014a,它也没有很好的记录它绝对可用。)
此时,字符串和日期列将是您的主要数据传输成本。如果您可以更改查询或架构以返回数字标识符,那么可能会加快速度。如果您的基数字符串列较低,则可以将它们转换为@categorical变量,以便在Matlab内部保存空间。
将日期检索为字符串非常昂贵。而且你希望它们最终成为datenums。您可以通过使用SQL编写的转换表达式将SQL DATE到Matlab datenum的转换推送到Access层,从而进一步加快速度。事实上,在此查询中,由于您已经将T1.DATE1修复为WHERE子句中的已知值,因此不要将其作为查询中的列进行检索。只需将列设置为Matlab层中的已知值即可。这样可以节省转移和转换日期值的费用,这些费用很昂贵。而是这样的东西。
setdbprefs('DataReturnFormat', 'table');
conn = database('Test_DB', '', '');
myDates = % ... a list of dates as datenums, not strings
for date = myDates
sql = [ 'SELECT DISTINCT T1.TF1, T1.SI1, T1.SI2, T2.TF2' ...
'FROM T2 INNER JOIN T1 ' ...
'ON T2.TF1 = T1.TF1 ' ...
'WHERE (((T1.DATE1)=#', datestr(date, 'yyyy-mm-dd'), '#));'];
curs = fetch(exec(conn, sql));
t = curs.Data;
t.DATE1 = repmat(date, [height(t) 1]);
% ... do stuff with t ...
end
尝试使用Native ODBC Connection method。这将节省JDBC-ODBC桥驱动程序的额外费用,这是普通database('DSN', '', '')
连接使用的。