从Delphi XE2高效地访问各种DBMS

时间:2013-04-15 13:40:51

标签: database performance delphi c++builder hana

我的需求

我使用Delphi / C ++ Builder XE2。

我至少需要访问这些 DBMS

  • 火鸟
  • DB2 / 400
  • SQL Server
  • SAP HANA(新的内存数据库,可用接口:JDBC,ODBC,ODBO,SQLDBC)

我需要在数据感知视觉控件中显示和编辑数据。 数据可以驻留在任何这些DBMS上,我将在外部文本文件上配置连接属性和SQL语句。

所以我正在寻找一组用于数据库访问的组件,它支持这样的DBMS并具有良好的性能,类似于旧的Paradox表。

我的猜测

  1. 使用ODBC性能将比使用本机驱动程序更差。如果是的话,我该如何克服这个问题?
  2. 即使通过ODBC,HANA内存数据库的性能也会很好(我现在无法测试)。
  3. 到目前为止我发现的

    • BDE(Borland数据库引擎)(TDatabaseTTable ...)

      弃用。

    • DBX(Embarcadero dbExpress)(TSQLConnectionTSQLTable ...)

      替换BDE,单向数据集(光标只向前移动;不在内存中缓冲数据,这样的数据集不能在DBGrid中显示;要使用dbExpress构建用户界面,您需要使用另外两个组件:{{ 1}}和TDataSetProvider

      使用本机驱动程序(HANA没有)或ODBC。

    • FireDAC(Embarcadero Fire数据访问组件)(TClientDataSetTADConnection ...)

      这是AnyDAC的延续;使用本机驱动程序(HANA没有)或ODBC或dbExpress。

    • UniDAC(Devart通用数据访问组件)

      不自由;使用本机驱动程序(HANA没有)或ODBC或“DB Client”。

    • DA(Delphi的RemObjects Data Abstract

      不自由。

    • ZDBC(Zeos数据库连接接口)(TADTableTZConnection ...)

      开源;从作为Object Pascal的JDBC端口开始;不提供与数据感知视觉控件的绑定。

    • dbGo(Embarcadero dbGo)(TZQueryTADOConnection ...)

      实现ADO(因此通过ODBC上的OLE DB)。有许多怪癖,比如在查询中重复同名的参数。

    • Jv BDE TADOTableTJvQuery ...)

      加强通讯标准库。

    • Jv数据访问TJvBDESQLScriptTJvADODataset ...)

      加强通讯标准库。

    (随意增强此列表)

    所以我的选择是

    • dbExpress或FireDAC:将来Embarcadero会去哪里?
    • dbGo:ADO是个不错的选择吗?似乎它依赖于ODBC,那么性能呢?
    • 像UniDAC或Data Abstract这样的商业产品:是否有必要?会更好吗?

5 个答案:

答案 0 :(得分:9)

我决定在Delphi XE3上进行一些性能研究:UniDAC(5.0.1)和FireDAC(8.0.1)。数据库:Firebird,MySQL& SQL Server。

以下是150k记录获取结果(内存使用率被视为提取之前和之后的差异)。

火鸟:

CREATE TABLE TEST_PERF (
    ID  INTEGER PRIMARY KEY,
    VC  VARCHAR(200),
    NM  NUMERIC(18,2),
    DT  TIMESTAMP
)

UniDAC - 0,909秒,吃了12 324 044的内存

FireDAC - 0,967秒,吃了282 179 668的记忆(我很震惊)

MySQL的:

CREATE TABLE TEST_PERF (
    ID  INTEGER PRIMARY KEY,
    VC  VARCHAR(200),
    NM  NUMERIC(18,2),
    DT  DATETIME
)

UniDAC - 0,363秒和11 552 604内存

FireDAC - 0,713秒和49 375 108内存

SQL Server:

CREATE TABLE TEST_PERF (
    ID  INTEGER PRIMARY KEY,
    VC  VARCHAR(200),
    NM  NUMERIC(18,2),
    DT  DATETIME
)

UniDAC - 0,391秒和14 155 576内存

FireDAC - 0,324秒和51 775 844内存

一切都只是简单地衡量:

function MemoryUsed: Cardinal;
var
  st: TMemoryManagerState;
  sb: TSmallBlockTypeState;
begin
  GetMemoryManagerState(st);
  Result := st.TotalAllocatedMediumBlockSize + st.TotalAllocatedLargeBlockSize;
  for sb in st.SmallBlockTypeStates do
    Result := Result + sb.UseableBlockSize * sb.AllocatedBlockCount;
end;

  UniQuery1.SQL.Text := 'select * from test_perf';
  UniQuery1.SpecificOptions.Values['FetchAll'] := 'True';
  mem := MemoryUsed;
  tc := Now;
  UniQuery1.Open;
  UniQuery1.Last;
  tc := Now - tc;
  mem := MemoryUsed - mem;
  Memo1.Lines.Add('UniDAC Firebird: Time: ' + FloatToStr(tc * 24 * 60 * 60) + ' sec; Memory used: ' + IntToStr(mem));

  ADQuery1.SQL.Text := 'select * from test_perf';
  ADQuery1.FetchOptions.Mode := fmAll;
  mem := MemoryUsed;
  tc := Now;
  ADQuery1.Open;
  ADQuery1.Last;
  tc := Now - tc;
  mem := MemoryUsed - mem;
  Memo1.Lines.Add('FireDAC Firebird: Time: ' + FloatToStr(tc * 24 * 60 * 60) + ' sec; Memory used: ' + IntToStr(mem));

如果有人有兴趣,这里是test application,你可以为ADO,dbExpress,ZeosLib和其他你感兴趣的人添加性能比较。

答案 1 :(得分:2)

始终使用ADO - 将它与SQLServer,Oracle,Sybase,PostGreSQL等一起使用。您可以为任何数据库找到ADO提供程序。从未遇到过问题我无法通过一些研究来解决问题。由于ADO被广泛使用,因此大多数问题都是众所周知的。 UDL文件可以让您的生活更轻松。

但我从不在组件面板上使用Delphi ADO组件 - 要么我在内存中使用它们,要么更常见的是,将ADO调用的结果直接转储到TKBMMemtable中并完全避免Delphi'开箱即用'的东西。您可以编写一个实用程序函数,为您自动完成。

答案 2 :(得分:1)

如果您使用的是XE2,我建议使用dbExpress。

  • 它支持ODBC(但不支持SAP HANA)
  • 单向数据集可与ClientDataSet一起用于缓存。实际上,ClientDataSets可用于缓存任何数据集组件。

如果您使用的是XE3或更高版本,我建议使用FireDAC。

  • Embarcadero购买了AnyDAC并将其重命名为FireDAC。
  • 它包含在企业SKU及以上版本中。许可的XE3用户可以免费下载。
  • 我相信这将是他们未来的数据访问策略。见this recent blog post

我理解FireDAC可以与XE2一起使用,但我不确定是否有任何问题。

答案 3 :(得分:0)

Firedac-与Delphi一起来,所以你可能无论如何都要付钱。 UNIDac-Faster让您不必频繁升级Delphi,以便更新数据,如果您有一天决定去Lazzarus,您也可以节省大量的工作。

答案 4 :(得分:-2)

许多线程中存在许多误解,所以我会尝试给出2美分。 问题是我们Delphians过去常常在executables进行思考,所以我们寻找移动数据的方法(特别是当我们的数据库和应用服务器在外面托管时);这些场景永远不会超过RIA应用程序,因为您不再移动数据,而只是屏幕的表示。 另一个误解是TDATASETAJAX不兼容。 只需查看UNIGUI上的一些youtube示例。顺便说一下,我使用普通的DataSnapclientdataset,而不是ORM。