gpt4 book ai didi

sql-server - SQL Server CE 4.0 性能对比

转载 作者:IT王子 更新时间:2023-10-29 06:17:12 26 4
gpt4 key购买 nike

SQL Server CE 4 (SQL Server Compact Edition 4.0) 已经不是新闻了(如果是,你可以 read this article)

但是看到 SQL Server CE 4 与其他数据库的性能比较非常有趣。

特别是:

  • SQLite
  • SQL Server (1)
  • SQL Server Express *
  • 也许火鸟

  • (1) 用于功能可比的应用程序。

    不幸的是,谷歌目前提供的关于该主题的链接并不多。实际上我找不到任何(对于正确的 SQL CE 版本)。

    如果有人能找到或分享这些信息,让我们在这里收集它,以供 future 的人类使用。

    最佳答案

    在我看来,将嵌入式数据库(如 SQL CE)与服务器端关系数据库(与所有其他数据库一样,除了 SQLite 和嵌入式版本的 Firebird)进行比较是不正确的。

    它们之间的主要区别在于通用服务器端关系数据库 (如 MS SQL、MySQL、Firebird Classic 和 SuperServer 等)作为独立服务安装和 在主应用程序范围之外运行 .这就是为什么它们可以表现得更好,因为对多核和多 CPU 架构的内在支持,使用预缓存、VSS 等操作系统功能来增加密集数据库操作的吞吐量,并且可以占用尽可能多的内存您的操作系统可以提供单个服务/应用程序。这也意味着它们的性能指标或多或少独立于您的应用程序,但在很大程度上取决于您的硬件。在这方面,我会说任何数据库的服务器版本与嵌入式数据库相比总是具有更高的性能。

    SQL CE(连同 Firebird Embedded、SQLite、TurboSQL 和其他一些)是 嵌入式数据库引擎 ,这意味着整个数据库被打包成一个(或最多 2 个)DLL 文件,这些文件与您的应用程序一起分发。由于明显的大小限制(您是否希望将 30 MB 的 DLL 与 2-3 MB 长的应用程序一起分发?)他们还直接在您的应用程序上下文中运行 和总数据访问操作的内存和性能与应用程序的其他部分共享 -- 这涉及可用内存、CPU 时间、磁盘吞吐量等。让计算密集型线程与数据访问线程并行运行可能会导致数据库性能急剧下降。

    由于应用领域不同,这些数据库有不同的选项:server-db 提供广泛的用户和权限管理,支持 View 和存储过程,而嵌入式数据库通常缺乏对用户和权限管理的支持,对 View 的支持有限和存储过程(后者失去了在服务器端运行的大部分好处)。数据吞吐量是 RDBMS 的一个常见瓶颈,服务器版本通常安装在 strip 化 RAID 卷上,而嵌入式 DB 通常是面向内存的(尝试将所有实际数据保存在内存中)并最小化数据存储访问操作。

    因此,比较适用于 .Net 的不同嵌入式 RDBMS 的性能可能更有意义,例如 MS SQL CE 4.0、SQLite、Firebird Embedded、TurboSQL。我不希望在通常的非高峰操作期间会有太大的差异,而由于与操作系统的更好集成,某些数据库可能会为大型 BLOB 提供更好的支持。

    - 更新 -

    我必须收回我最后的话,因为我的快速实现显​​示了非常有趣的结果。

    我写了一个简短的控制台应用程序来测试这两个数据提供者,如果你想自己试验它们,这里是你的源代码。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.SQLite;
    using System.Data.SqlServerCe;
    using System.Data.Common;

    namespace TestSQL
    {
    class Program
    {
    const int NUMBER_OF_TESTS = 1000;

    private static string create_table;

    private static string create_table_sqlce = "CREATE TABLE Test ( id integer not null identity primary key, textdata nvarchar(500));";
    private static string create_table_sqlite = "CREATE TABLE Test ( id integer not null primary key, textdata nvarchar(500));";

    private static string drop_table = "DROP TABLE Test";
    private static string insert_data = "INSERT INTO Test (textdata) VALUES ('{0}');";
    private static string read_data = "SELECT textdata FROM Test WHERE id = {0}";
    private static string update_data = "UPDATE Test SET textdata = '{1}' WHERE id = {0}";
    private static string delete_data = "DELETE FROM Test WHERE id = {0}";

    static Action<DbConnection> ACreateTable = (a) => CreateTable(a);
    static Action<DbConnection> ATestWrite = (a) => TestWrite(a, NUMBER_OF_TESTS);
    static Action<DbConnection> ATestRead = (a) => TestRead(a, NUMBER_OF_TESTS);
    static Action<DbConnection> ATestUpdate = (a) => TestUpdate(a, NUMBER_OF_TESTS);
    static Action<DbConnection> ATestDelete = (a) => TestDelete(a, NUMBER_OF_TESTS);
    static Action<DbConnection> ADropTable = (a) => DropTable(a);

    static Func<Action<DbConnection>,DbConnection, TimeSpan> MeasureExecTime = (a,b) => { var start = DateTime.Now; a(b); var finish = DateTime.Now; return finish - start; };

    static Action<string, TimeSpan> AMeasureAndOutput = (a, b) => Console.WriteLine(a, b.TotalMilliseconds);

    static void Main(string[] args)
    {
    // opening databases
    SQLiteConnection.CreateFile("sqlite.db");
    SQLiteConnection sqliteconnect = new SQLiteConnection("Data Source=sqlite.db");
    SqlCeConnection sqlceconnect = new SqlCeConnection("Data Source=sqlce.sdf");

    sqlceconnect.Open();
    sqliteconnect.Open();

    Console.WriteLine("=Testing CRUD performance of embedded DBs=");
    Console.WriteLine(" => Samplesize: {0}", NUMBER_OF_TESTS);

    create_table = create_table_sqlite;
    Console.WriteLine("==Testing SQLite==");
    DoMeasures(sqliteconnect);

    create_table = create_table_sqlce;
    Console.WriteLine("==Testing SQL CE 4.0==");
    DoMeasures(sqlceconnect);



    Console.ReadKey();

    }

    static void DoMeasures(DbConnection con)
    {
    AMeasureAndOutput("Creating table: {0} ms", MeasureExecTime(ACreateTable, con));
    AMeasureAndOutput("Writing data: {0} ms", MeasureExecTime(ATestWrite, con));
    AMeasureAndOutput("Updating data: {0} ms", MeasureExecTime(ATestUpdate, con));
    AMeasureAndOutput("Reading data: {0} ms", MeasureExecTime(ATestRead, con));
    AMeasureAndOutput("Deleting data: {0} ms", MeasureExecTime(ATestDelete, con));
    AMeasureAndOutput("Dropping table: {0} ms", MeasureExecTime(ADropTable, con));
    }



    static void CreateTable(DbConnection con)
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = create_table;
    sqlcmd.ExecuteNonQuery();
    }

    static void TestWrite(DbConnection con, int num)
    {
    for (; num-- > 0; )
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = string.Format(insert_data,Guid.NewGuid().ToString());
    sqlcmd.ExecuteNonQuery();
    }

    }

    static void TestRead(DbConnection con, int num)
    {
    Random rnd = new Random(DateTime.Now.Millisecond);
    for (var max = num; max-- > 0; )
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = string.Format(read_data, rnd.Next(1,num-1));
    sqlcmd.ExecuteNonQuery();
    }
    }

    static void TestUpdate(DbConnection con, int num)
    {
    Random rnd = new Random(DateTime.Now.Millisecond);
    for (var max = num; max-- > 0; )
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = string.Format(update_data, rnd.Next(1, num - 1), Guid.NewGuid().ToString());
    sqlcmd.ExecuteNonQuery();
    }
    }

    static void TestDelete(DbConnection con, int num)
    {
    Random rnd = new Random(DateTime.Now.Millisecond);
    var order = Enumerable.Range(1, num).ToArray<int>();
    Action<int[], int, int> swap = (arr, a, b) => { int c = arr[a]; arr[a] = arr[b]; arr[b] = c; };

    // shuffling the array
    for (var max=num; max-- > 0; ) swap(order, rnd.Next(0, num - 1), rnd.Next(0, num - 1));


    foreach(int index in order)
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = string.Format(delete_data, index);
    sqlcmd.ExecuteNonQuery();
    }
    }

    static void DropTable(DbConnection con)
    {
    var sqlcmd = con.CreateCommand();
    sqlcmd.CommandText = drop_table;
    sqlcmd.ExecuteNonQuery();
    }


    }
    }

    必要的免责声明:
  • 我在我的机器上得到了这些结果: Dell Precision WorkStation T7400 配备 2 个 Intel Xeon E5420 CPU 和 8GB RAM,运行 64 位 Win7 Enterprise .
  • 我用了 两个数据库的默认设置 带有连接字符串“Data Source=database_file_name”。
  • 我使用了 SQL CE 4.0 和 SQLite/System.Data.SQLite 的最新版本(从今天开始,2011 年 6 月 3 日)。

  • 以下是两个不同样本的结果:

    > =测试嵌入式数据库的CRUD性能=
    > => 样本量:200
    > ==测试SQLite==
    > 创建表:396.0396 毫秒
    > 写入数据:22189.2187 ms
    > 更新数据:23591.3589 毫秒
    > 读取数据:21.0021 毫秒
    > 删除数据:20963.0961 毫秒
    > 丢弃表:85.0085 毫秒

    > ==测试 SQL CE 4.0==
    > 创建表:16.0016 毫秒
    > 写入数据:25.0025 ms
    > 更新数据:56.0056 毫秒
    > 读取数据:28.0028 毫秒
    > 删除数据:53.0053 毫秒
    > 丢弃表:11.0011 毫秒

    ...以及更大的样本:

    =测试嵌入式数据库的 CRUD 性能=
    => 样本量:1000
    ==测试SQLite==
    创建表:93.0093 毫秒
    写入数据:116632.6621 ms
    更新数据:104967.4957 毫秒
    读取数据:134.0134 毫秒
    删除数据:107666.7656 毫秒
    丢弃表:83.0083 毫秒

    ==测试 SQL CE 4.0==
    创建表:16.0016 毫秒
    写入数据:128.0128 毫秒
    更新数据:307.0307 毫秒
    读取数据:164.0164 毫秒
    删除数据:306.0306 毫秒
    丢弃表:13.0013 毫秒

    因此,如您所见,与 SQLCE 相比,任何写入操作(创建、更新、删除)在 SQLite 中都需要多出近 1000 倍的时间。它不一定反射(reflect)该数据库的总体性能不佳,可能是由于以下原因:
  • 我用于 SQLite 的数据提供程序是 System.Data.SQLite ,这是一个包含托管和非托管代码的混合程序集(SQLite 最初完全用 C 编写,DLL 仅提供绑定(bind))。可能 P/Invoke 和数据编码(marshal)占用了大量的操作时间。
  • 默认情况下,SQLCE 4.0 很可能将所有数据缓存在内存中,而 SQLite 每次发生更改时都会将大部分数据更改直接刷新到磁盘存储中。可以通过连接字符串为两个数据库提供数百个参数并适当调整它们。
  • 我使用了一系列单个查询来测试数据库。至少 SQLCE 通过更适合这里的特殊 .Net 类支持批量操作。如果 SQLite 也支持它们(抱歉,我不是这里的专家,我的快速搜索没有产生任何希望),也可以比较它们。
  • 我在 x64 机器上观察到 SQLite 的许多问题(使用相同的 .net 适配器):从数据连接意外关闭到数据库文件损坏。我认为数据适配器或库本身存在一些稳定性问题。
  • 关于sql-server - SQL Server CE 4.0 性能对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5249240/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com