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

标签 sql-server performance sqlite sql-server-ce

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)适用于功能可比的应用程序。

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

如果可以找到或共享此类信息,请在此处收集以供将来人类使用。

最佳答案

我认为,将嵌入式数据库(如SQL CE)与服务器端关系数据库(如所有其余部分,除了SQLite和Firebird的嵌入式版本)进行比较是不正确的。

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

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

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

因此,有意义的是比较.NET的不同嵌入式RDBMS的性能,例如MS SQL CE 4.0,SQLite,Firebird Embedded和TurboSQL。我不希望在通常的非高峰操作期间出现巨大的差异,但是由于与OS更好的集成,某些数据库可能会为大型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();
        }


    }
}


必要的免责声明:


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


这是两个不同样本的结果:

> =测试嵌入式数据库的CRUD性能=
> =>样本大小:200
> ==测试SQLite ==
>建立表格:396.0396 ms
>写入数据:22189.2187 ms
>更新数据:23591.3589 ms
>读取数据:21.0021 ms
>删除数据:20963.0961 ms
>下降表:85.0085毫秒

> ==正在测试SQL CE 4.0 ==
>建立表格:16.0016毫秒
>写入数据:25.0025毫秒
>更新数据:56.0056 ms
>读取数据:28.0028毫秒
>删除数据:53.0053毫秒
>下降表:11.0011毫秒


...以及更大的样本:

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

==正在测试SQL CE 4.0 ==
创建表:16.0016 ms
写入数据:128.0128 ms
更新数据:307.0307毫秒
读取数据:164.0164 ms
删除数据:306.0306 ms
下降台:13.0013毫秒


因此,您可以看到,与SQLCE相比,SQLite中的任何写入操作(创建,更新,删除)都需要将近1000倍的时间。它不一定反映此数据库的一般性能不佳,可能是由于以下原因:


我用于SQLite的数据提供程序是System.Data.SQLite,它是包含托管和非托管代码的混合程序集(SQLite最初完全用C编写,而DLL仅提供绑定)。 P / Invoke和数据封送可能会占用大量的操作时间。
默认情况下,很可能SQLCE 4.0默认将所有数据缓存在内存中,而每次更改发生时,SQLite都会将大多数数据更改直接刷新到磁盘存储中。一个人可以通过连接字符串为两个数据库提供数百个参数,并对其进行适当的调整。
我使用了一系列单个查询来测试数据库。至少SQLCE通过特殊的.Net类支持批量操作,该类更适合这里。如果SQLite也支持它们(对不起,我不是这里的专家,我的快速搜索没有任何希望),也可以对它们进行比较。
我已经在x64机器(使用相同的.net适配器)上观察到SQLite的许多问题:从数据连接意外关闭到数据库文件损坏。我认为数据适配器或库本身存在一些稳定性问题。

关于sql-server - SQL Server CE 4.0性能比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7274112/

相关文章:

sql - 更新一行更快,还是删除它并插入新行更快?

python - 无法从 SQLITE3 数据库中获取最后一行 ID

php - 使用PHP在SQLite中实现SQL AES ENCRYPTION

sql-server - SQL 两条Select命令一张单表输出

javascript - Web 表单页面的性能或页面加载时间检查

sql-server - 从表中选择特定记录

python - 用于两端排序列表的最佳数据结构

python - Sqlalchemy 从一个表中的一列查询多行

c# - "Error in connection"使用 ado.net C# 使用插入命令访问数据库时

mysql - 将MSSQL表记录导出到MySQL的.sql文件中