SQLite与Microsoft Access MDB相比有多快?

Uwe*_*eim 14 .net sqlite ms-access jet

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

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

我对性能的质疑是:

是否有任何性能基准测试比较MDB和SQLite对相当小的数据集?

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

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

更新

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

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

更新2

刚刚发现这个文档表明了一些速度比较,遗憾的是没有MDB,据我所知.

更新3

根据要求,一些数字:

  • 约.数据库中有30个表.
  • 大多数表格的方式低于100条记录.
  • 约.5个表通常有几百到几千条记录.
  • 一个大型MDB文件大约为60 MB.

更新4

换句话说:我当前的MDB实现没有任何性能问题.我问这个问题是为了感觉在使用SQLite而不是MDB时性能是否相等(或更好).

Uwe*_*eim 12

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

我还添加了更多数据库.

我测试过的数据库

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

由于某些数据库不支持连接池,我做了两个测试:

  1. 一次测试通过using块尽快关闭连接.
  2. 另一个测试,在整个应用程序生命周期内始终打开与每个数据库的连接

立即关闭连接时的测试结果

  • 在本地运行的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是我测试中最慢的数据库.

立即关闭连接时,我的测试应用程序的详细输出

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
Run Code Online (Sandbox Code Playgroud)

保持连接打开时我的测试应用程序的详细输出

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
Run Code Online (Sandbox Code Playgroud)

  • 查看 pastebin 代码,您没有为 SQLite 启用池(默认情况下关闭)。对我来说插入 1000 recs (SQLite) 的简单测试是 17-19 秒。**启用池**(并且仍在处理连接)接近一半:9.1 - 10.9。与使用一个开放连接几乎相同:9.4 - 10.2。 (2认同)

Han*_*sUp 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
Run Code Online (Sandbox Code Playgroud)


Alb*_*lal 5

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

在我看来,您正在通过改变工具而不是改变设计和方法来寻找解决方案。事实上,对于大多数操作来说,access jet 引擎比诸如 oracle、mySQL 或 SQL 服务器之类的东西快得多。原因是那些其他系统是大量基于服务器的系统,它们具有到服务器的套接字连接。它们具有多层事务处理。在您和驻留在硬盘驱动器上的实际数据之间可能有 500 层额外的软件和系统。

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

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

现在当然,如果您谈论通过某种类型的网络进行连接,那么那些基于服务器的系统会更好,因为您希望在任何数据开始沿着网络管道向下流动之前进行所有处理和所有这些 majic。

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

Access 可以在不到一秒的时间内对 150,000 条记录进行连接、分类和汇总,并且可以连接多个表。

另一方面,在这些系统中的任何一个中,通常较大的开销是打开到特定表的连接。实际上,打开一个表所花费的时间大约是传输 30,000 条记录的成本。所以,这意味着你要确保你的代码和使用这些表不会不必要地打开一个新表(特别是在某些类型的代码循环中。换句话说,即使在重复执行一条 SQL 插入命令的地方,你'最好打开一个记录集,然后以这种方式插入,因为这样你就不再使用 SQL 命令了,并且为每一行插入你'

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

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

换句话说,你是在找错树,而寻求改变工具以修复性能的开发人员只是通过指责工具来寻找修复方法,而在大多数情况下,问题出在所采用的设计上。

  • 据我所知,SQLLite 与 MySQL 没有任何关系。 (8认同)
  • -1 表示刚刚编造出来的,没有现实依据的段落 (4认同)
  • @大卫。此外,“500 甚至 1000 额外代码层”这行只是纯粹的妄想,毫无意义。即使是真的,像层这样的抽象概念与系统的执行方式之间也不存在一对一的相关性。 (3认同)
  • 我完全同意。30 个表和大约 100 条记录不会成为性能问题,除非您的设计或代码在某种程度上是错误的。 (2认同)