SQLite与Microsoft Access MDB相比有多快?

时间:2011-06-24 15:57:38

标签: .net sqlite ms-access jet

目前我正在考虑通过SQlite数据库替换单用户.NET C#Windows窗体应用程序上的Microsoft Jet MDB数据库的使用。

我的目标是降低Jet驱动程序等安装要求以及Jet安装损坏时的一些令人讨厌的错误(我们不时地向客户报告这些错误)。

关于效果的问题是:

是否有任何性能基准测试将MDB和SQLite与一组相当小的数据进行比较?

或者是否有任何开发人员已经采取了这一步骤,可以根据自己的经验讲述一些故事?

(我现在谷歌搜索几个小时没有成功)

更新

虽然数据库不包含 许多记录和表格,但我认为性能仍然是一个问题,因为数据经常被访问。

该应用程序是一个所谓的“桌面CMS系统”,它呈现HTML页面;在渲染过程中,正在访问大量数据,并且正在执行大量SQL查询。

更新2

刚刚找到this documentation表示一些速度比较,遗憾的是没有使用MDB,据我所见。

更新3

根据要求,有些数字:

  • 约数据库中有30个表。
  • 大多数表格都低于100条记录。
  • 约5张表,通常有几百到几千条记录。
  • 大型MDB文件大约为60 MB。

更新4

重新说一句:我在当前的MDB实现中遇到任何性能问题。我问这个问题是为了让人感觉在使用SQLite而不是MDB时性能是否相等(或更好)。

4 个答案:

答案 0 :(得分:12)

4年多以后,我实际上在MDB和SQLite之间进行了一次小的(可能有些天真的)性能对比测试。

我还添加了更多数据库。

我测试的数据库

  • SQL Server Express 2014在与测试应用程序相同的本地PC和本地SSD驱动器上。
  • 在千兆位LAN中的服务器上安装SQL Server Express 2014。
  • 与测试应用程序在同一本地PC和本地SSD驱动器上的SQL Server Compact(CE)。
  • Microsoft Access MDB / Jet在与测试应用程序相同的本地PC和本地SSD驱动器上。
  • 与测试应用程序在同一本地PC和本地SSD驱动器上的Microsoft SQLite。
  • 与测试应用程序在同一本地PC和本地SSD驱动器上的Microsoft VistaDB 5。

some databases do not support connection pooling以来,我做了两次测试:

  1. 通过using阻止尽快关闭连接的一项测试。
  2. 在整个应用程序生命周期内始终与每个数据库建立连接的另一项测试
  3. 立即关闭连接时的测试结果

    • 本地运行的SQL Express最快。
    • 我们本地网络上的SQL Express处于第二位。
    • SQL Compact Edition(CE)比SQLite和Jet / MDB快得多。
    • Jet / MDB比SQLite快一点,比SQL CE慢得多。
    • SQLite比Jet / MDB慢一点。
    • VistaDB 5是我测试中最慢的数据库。

    保持连接打开时的测试结果

    结果与立即关闭连接时的结果非常相似。

    相对于彼此,从最快到最慢的顺序没有改变。一些没有实际连接池的数据库提高了它们的绝对性能。

    • 本地运行的SQL Express最快。
    • 我们本地网络上的SQL Express处于第二位。
    • SQL Compact Edition(CE)比SQLite和Jet / MDB快得多。
    • Jet / MDB比SQLite快一点,比SQL CE慢得多。
    • SQLite比Jet / MDB慢一点。
    • VistaDB 5是我测试中最慢的数据库。

    立即关闭连接时test application的详细输出

    1.: 1 x DELETE FROM Tabelle1 (Closing connections):
    - SQL Express local : 00:00:00.1723705
    - SQL Express remote: 00:00:00.2093229
    - SQL CE            : 00:00:00.3141897
    - MS Access         : 00:00:00.3854029
    - SQLite            : 00:00:00.4639365
    - VistaDB           : 00:00:00.9699047
    
    2.: 1 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (Closing connections):
    - SQL Express local : 00:00:00.0039836
    - SQL Express remote: 00:00:00.0062002
    - SQL CE            : 00:00:00.0432679
    - MS Access         : 00:00:00.0817834
    - SQLite            : 00:00:00.0933030
    - VistaDB           : 00:00:00.1200426
    
    3.: 10 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (Closing connections):
    - SQL Express local : 00:00:00.0031593
    - SQL Express remote: 00:00:00.0142514
    - SQL CE            : 00:00:00.3724224
    - MS Access         : 00:00:00.7474003
    - SQLite            : 00:00:00.8818905
    - VistaDB           : 00:00:00.9342783
    
    4.: 100 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (Closing connections):
    - SQL Express local : 00:00:00.0242817
    - SQL Express remote: 00:00:00.1124771
    - SQL CE            : 00:00:03.6239390
    - MS Access         : 00:00:07.3752378
    - SQLite            : 00:00:08.6489843
    - VistaDB           : 00:00:09.0933903
    
    5.: 1000 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (Closing connections):
    - SQL Express local : 00:00:00.2735537
    - SQL Express remote: 00:00:01.2657006
    - SQL CE            : 00:00:36.2335727
    - MS Access         : 00:01:13.8782439
    - SQLite            : 00:01:27.1783328
    - VistaDB           : 00:01:32.0760340
    
    6.: 1 x SELECT * FROM Tabelle1 (Closing connections):
    - SQL Express local : 00:00:00.0520670
    - SQL Express remote: 00:00:00.0570562
    - SQL CE            : 00:00:00.1026963
    - MS Access         : 00:00:00.1646635
    - SQLite            : 00:00:00.1785981
    - VistaDB           : 00:00:00.2311263
    
    7.: 10 x SELECT * FROM Tabelle1 (Closing connections):
    - SQL Express local : 00:00:00.0183055
    - SQL Express remote: 00:00:00.0501115
    - SQL CE            : 00:00:00.3235680
    - MS Access         : 00:00:00.7119203
    - SQLite            : 00:00:00.7533361
    - VistaDB           : 00:00:00.9804508
    
    8.: 100 x SELECT * FROM Tabelle1 (Closing connections):
    - SQL Express local : 00:00:00.1787837
    - SQL Express remote: 00:00:00.4321814
    - SQL CE            : 00:00:03.0401779
    - MS Access         : 00:00:06.8338598
    - SQLite            : 00:00:07.2000139
    - VistaDB           : 00:00:09.1889217
    
    9.: 1000 x SELECT * FROM Tabelle1 (Closing connections):
    - SQL Express local : 00:00:01.6112566
    - SQL Express remote: 00:00:03.9542611
    - SQL CE            : 00:00:29.1209991
    - MS Access         : 00:01:07.2309769
    - SQLite            : 00:01:10.3167922
    - VistaDB           : 00:01:31.4312770
    
    10.: 1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.0029406
    - SQL Express remote: 00:00:00.0088138
    - SQL CE            : 00:00:00.0498847
    - MS Access         : 00:00:00.0893892
    - SQLite            : 00:00:00.0929506
    - VistaDB           : 00:00:00.2575795
    
    11.: 10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.0174026
    - SQL Express remote: 00:00:00.0400797
    - SQL CE            : 00:00:00.3408818
    - MS Access         : 00:00:00.7314978
    - SQLite            : 00:00:00.7653330
    - VistaDB           : 00:00:01.9565675
    
    12.: 100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.1565402
    - SQL Express remote: 00:00:00.3787208
    - SQL CE            : 00:00:03.3516629
    - MS Access         : 00:00:07.2521126
    - SQLite            : 00:00:07.5618047
    - VistaDB           : 00:00:19.5181391
    
    13.: 1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:01.5686470
    - SQL Express remote: 00:00:03.7414669
    - SQL CE            : 00:00:35.3944204
    - MS Access         : 00:01:14.6872377
    - SQLite            : 00:01:17.9964955
    - VistaDB           : 00:03:18.1902279
    
    14.: 1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.0053295
    - SQL Express remote: 00:00:00.0089722
    - SQL CE            : 00:00:00.0395485
    - MS Access         : 00:00:00.0797776
    - SQLite            : 00:00:00.0833477
    - VistaDB           : 00:00:00.2554930
    
    15.: 10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.0168467
    - SQL Express remote: 00:00:00.0552233
    - SQL CE            : 00:00:00.3929877
    - MS Access         : 00:00:00.7886399
    - SQLite            : 00:00:00.8209904
    - VistaDB           : 00:00:02.1248734
    
    16.: 100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:00.1705345
    - SQL Express remote: 00:00:00.3969228
    - SQL CE            : 00:00:03.4886826
    - MS Access         : 00:00:07.4564258
    - SQLite            : 00:00:07.7828646
    - VistaDB           : 00:00:20.4092926
    
    17.: 1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (Closing connections):
    - SQL Express local : 00:00:01.6237424
    - SQL Express remote: 00:00:03.9816212
    - SQL CE            : 00:00:35.1441759
    - MS Access         : 00:01:14.7739758
    - SQLite            : 00:01:17.9477049
    - VistaDB           : 00:03:24.0049633
    

    保持连接打开时test application的详细输出

    1.: 1 x DELETE FROM Tabelle1 (keeping connection open):
    - SQL Express local : 00:00:00.0426930
    - SQL Express remote: 00:00:00.0546357
    - SQL CE            : 00:00:00.0786765
    - MS Access         : 00:00:00.0909099
    - SQLite            : 00:00:00.1101572
    - VistaDB           : 00:00:00.4637726
    
    2.: 1 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (keeping connection open):
    - SQL Express local : 00:00:00.0030936
    - SQL Express remote: 00:00:00.0051136
    - SQL CE            : 00:00:00.0054226
    - MS Access         : 00:00:00.0074847
    - SQLite            : 00:00:00.0154474
    - VistaDB           : 00:00:00.0373701
    
    3.: 10 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (keeping connection open):
    - SQL Express local : 00:00:00.0023271
    - SQL Express remote: 00:00:00.0109913
    - SQL CE            : 00:00:00.0119872
    - MS Access         : 00:00:00.0152531
    - SQLite            : 00:00:00.1131698
    - VistaDB           : 00:00:00.1261859
    
    4.: 100 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (keeping connection open):
    - SQL Express local : 00:00:00.0201695
    - SQL Express remote: 00:00:00.0888872
    - SQL CE            : 00:00:00.0966017
    - MS Access         : 00:00:00.1256167
    - SQLite            : 00:00:01.3632978
    - VistaDB           : 00:00:01.9422151
    
    5.: 1000 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}') (keeping connection open):
    - SQL Express local : 00:00:00.1693362
    - SQL Express remote: 00:00:00.9181297
    - SQL CE            : 00:00:01.0366334
    - MS Access         : 00:00:01.2794199
    - SQLite            : 00:00:13.9398816
    - VistaDB           : 00:00:19.8319476
    
    6.: 1 x SELECT * FROM Tabelle1 (keeping connection open):
    - SQL Express local : 00:00:00.0481500
    - SQL Express remote: 00:00:00.0507066
    - SQL CE            : 00:00:00.0738698
    - MS Access         : 00:00:00.0911707
    - SQLite            : 00:00:00.1012425
    - VistaDB           : 00:00:00.1515495
    
    7.: 10 x SELECT * FROM Tabelle1 (keeping connection open):
    - SQL Express local : 00:00:00.0157947
    - SQL Express remote: 00:00:00.0692206
    - SQL CE            : 00:00:00.0898558
    - MS Access         : 00:00:00.1196514
    - SQLite            : 00:00:00.1400944
    - VistaDB           : 00:00:00.3227485
    
    8.: 100 x SELECT * FROM Tabelle1 (keeping connection open):
    - SQL Express local : 00:00:00.1517498
    - SQL Express remote: 00:00:00.3399897
    - SQL CE            : 00:00:00.5497382
    - MS Access         : 00:00:00.8619646
    - SQLite            : 00:00:01.0463369
    - VistaDB           : 00:00:02.8607334
    
    9.: 1000 x SELECT * FROM Tabelle1 (keeping connection open):
    - SQL Express local : 00:00:01.5042900
    - SQL Express remote: 00:00:03.8431985
    - SQL CE            : 00:00:05.9075477
    - MS Access         : 00:00:09.2642402
    - SQLite            : 00:00:11.4427914
    - VistaDB           : 00:00:30.8470936
    
    10.: 1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.0033803
    - SQL Express remote: 00:00:00.0062499
    - SQL CE            : 00:00:00.0141105
    - MS Access         : 00:00:00.0188573
    - SQLite            : 00:00:00.0208236
    - VistaDB           : 00:00:00.1796513
    
    11.: 10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.0168644
    - SQL Express remote: 00:00:00.0377185
    - SQL CE            : 00:00:00.1121558
    - MS Access         : 00:00:00.1599104
    - SQLite            : 00:00:00.1799435
    - VistaDB           : 00:00:01.4042534
    
    12.: 100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.1547275
    - SQL Express remote: 00:00:00.3692526
    - SQL CE            : 00:00:01.1215470
    - MS Access         : 00:00:01.5577172
    - SQLite            : 00:00:01.7519790
    - VistaDB           : 00:00:14.5687575
    
    13.: 1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:01.4992800
    - SQL Express remote: 00:00:03.7601806
    - SQL CE            : 00:00:11.1738426
    - MS Access         : 00:00:15.8112902
    - SQLite            : 00:00:17.8045042
    - VistaDB           : 00:02:21.4492368
    
    14.: 1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.0048145
    - SQL Express remote: 00:00:00.0076790
    - SQL CE            : 00:00:00.0152074
    - MS Access         : 00:00:00.0204568
    - SQLite            : 00:00:00.0229056
    - VistaDB           : 00:00:00.2091614
    
    15.: 10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.0156564
    - SQL Express remote: 00:00:00.0377571
    - SQL CE            : 00:00:00.1138433
    - MS Access         : 00:00:00.1598932
    - SQLite            : 00:00:00.1793267
    - VistaDB           : 00:00:01.4667061
    
    16.: 100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:00.1512625
    - SQL Express remote: 00:00:00.4658652
    - SQL CE            : 00:00:01.2441809
    - MS Access         : 00:00:01.7224126
    - SQLite            : 00:00:01.9297231
    - VistaDB           : 00:00:14.9351318
    
    17.: 1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID (keeping connection open):
    - SQL Express local : 00:00:01.5223833
    - SQL Express remote: 00:00:03.9885174
    - SQL CE            : 00:00:11.8356048
    - MS Access         : 00:00:16.5977939
    - SQLite            : 00:00:18.6504260
    - VistaDB           : 00:02:26.0513056
    

    2019年4月更新1

    我做了一些测试,将Microsoft Access MDB与LiteDB(.NET的嵌入式数据库)进行了比较。

    再次,一些相当天真的比较,但我仍然想要一种感觉。

    This code进行1000次读写并产生以下值:

    Access             of 1000 WRITE iterations took 00:00:39.6488351.
    LiteDB             of 1000 WRITE iterations took 00:00:01.6596646.
    LiteDB (in-memory) of 1000 WRITE iterations took 00:00:00.1617220.
    Access             of 1000 READ  iterations took 00:00:48.8517302.
    LiteDB             of 1000 READ  iterations took 00:00:00.0082401.
    LiteDB (in-memory) of 1000 READ  iterations took 00:00:00.0097933.
    

    所以在我的场景中,LiteDB 更快。

    2019年4月更新2

    与VistaDB 5相比,我还针对VistaDB 6 Beta 1运行了原始代码。

    我的速度效果非常相似。与VistaDB 5相比,VistaDB 6的Beta稍微慢一点,很可能是因为它是一个调试版本。

    作为结论,我在VistaDB 5和VistaDB 6 Beta 1之间的场景中看到 no 显着的性能改进。我将不得不再次使用VistaDB 6的最终版本。

答案 1 :(得分:8)

如果您决定进行自己的基准测试,我提供此过程将Jet表导出为CSV文件。然后,您可以将它们导入SQLite数据库。

Public Sub DumpTablesAsCsv()
    Dim db As DAO.Database
    Dim tdf As DAO.TableDef
    Dim strCsvFile As String
    Dim strFolder As String
    Dim strTable As String

    strFolder = CurrentProject.Path & Chr(92)
    Set db = CurrentDb
    For Each tdf In db.TableDefs
        strTable = tdf.Name
        If Not (strTable Like "MSys*" Or strTable Like "~*") Then
            strCsvFile = strFolder & strTable & ".csv"
            DoCmd.TransferText acExportDelim, , strTable, _
                strCsvFile, HasFieldNames:=True
        End If
    Next tdf
    Set tdf = Nothing
    Set db = Nothing
End Sub

答案 2 :(得分:4)

实际上,事实上,我不确定你是否真的在这里提出正确的问题。

听起来,您正在通过更改工具,而不是更改设计和方法来寻找解决方案。事实上,对于大多数操作来说,访问喷气引擎比oracle,mySQL或SQL服务器快得多。原因是那些其他系统是大量基于服务器的系统,它们具有到服务器的套接字连接。它们具有多层事务处理。您和存储在硬盘驱动器上的实际数据之间可能有500个额外的软件和系统层。

对比访问本质上是一个进程内程序(而不是正在运行的服务)。您没有像使用基于服务器的系统那样通过某些TCP / IP连接连接到Access数据文件(事实上,大多数基于服务器的系统都会强制您通过网络层连接,即使在本地计算机上也是如此,而不是使用本地计算机内存连接,假设该选项可用。)

JET(Access数据库引擎)不是服务,只是将文件从硬盘驱动器上刮下并显示结果。从磁盘驱动器中抓取数据的速度与oracle或SQL服务器以及所有其他系统(我们在这里假设相同的机器和硬件)的速度相同。然而,那些其他系统仍然有另外500个甚至1000个额外的代码层和软件和网络连接以及大量的用户安全等等。所有这些都大大减慢了大量访问磁盘驱动器上的数据。

现在当然,如果你谈论通过某种类型的网络建立连接,那么那些基于服务器的系统会更好,因为你希望在任何数据开始流入网络管道之前,所有处理和所有这些处理都会发生。

但是在您的方案中,服务器和计算机是同一个。因此,消除数以千计的额外软件层的大量背景是完全有意义的。正如我所指出的,以及这些类型的场景,jet可以是基于服务器的系统(如MySql或Oracle)速度的50%甚至两倍。

访问可以加入,分类和总计库存,以便在一秒钟内完成150,000条记录,并且可以加入多个表格。

另一方面,在任何这些系统中,通常大的开销是打开与特定表的连接。实际上,打开表所花费的时间大约是要传输的30,000条记录的成本。所以,这意味着你要确保你的代码和这些表的使用没有必要打开一个新的表(特别是在某种类型的代码循环中。换句话说,即使在重复执行插入命令的地方,你,你打开记录集会好得多,然后就这样插入,因为那时你不再使用SQL命令了,对于每一行插入你都没有对该sql中的文本执行单独的解析(当以这种方式使用访问时,这可以使性能提高大约100倍 - 换句话说,这里经常引用的建议是使用SQL命令比打开记录集更快,这是完全错误的。)

这意味着,如果您在这里遇到某种减速,我会查看您的代码和设计,并确保不会重复打开和关闭记录集和数据集。鉴于您在此提及的文件很小,您不应该在数据操作中遇到任何明显的延迟。

公平地说,sqlLITE也是(我相信)基于进程的非服务器版本的MySql,并且上面提到的大多数优点也适用。但话说回来,你的瓶颈在每种情况下都不会有太大不同,因此我们回到这里设计问题。

换句话说,你正在咆哮错误的树,并且寻找工具变化来修复性能的开发人员只是在大多数情况下通过指责工具来解决问题在于所采用的设计

答案 3 :(得分:3)

自从Windows 2000以来,Jet 4.0,DAO,MDAC和ADO已作为Windows操作系统的一部分包含在内。因此,无需在应用程序中分发任何Jet“驱动程序”。