SQL Server CE 4(SQL Server Compact Edition 4.0)已不是新闻(如果是,您可以read this article)
但是看到SQL Server CE 4与其他数据库的性能比较非常有趣。
特别是:
(1)适用于功能相当的应用程序。
不幸的是,目前google提供的主题没有那么多链接。实际上我找不到任何(适当的SQL CE版本)。
如果有人能够找到或分享这些信息,我们可以在这里收集它以供将来人道使用。
答案 0 :(得分:17)
答案 1 :(得分:14)
以下是关于CodeProject网页基准测试的新近出版的文章:
Benchmarking the performance of embedded DB for .Net: SQL CE 4.0 vs SQLite
(该文章现在处于暂挂状态,您需要登录CodeProject才能访问其内容)
P.S。:我错误地将我以前的答案标记为社区维基条目,并且不会因此获得任何声誉。这鼓励我为Code Project撰写关于此主题的文章,其中包含一些优化的代码,有关嵌入式dbs的更多其他信息以及结果的统计分析。所以,如果您喜欢这篇文章和我的第二个答案,请将此答案投票。
答案 2 :(得分:10)
因为我在Alaudo的测试,测试结果以及最终的结论方面遇到了真正的困难,所以我继续使用他的程序玩了一下并提出了修改版本。
它测试以下每个10次并输出平均时间:
这是程序(实际上是一个类):
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlServerCe;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
class SqliteAndSqlceSpeedTesting
{
class Results
{
public string test_details;
public long create_table_time, insert_time, update_time, select_time, delete_time, drop_table_time;
}
enum DbType { Sqlite, Sqlce };
const int NUMBER_OF_TESTS = 200;
const string create_table_sqlite = "CREATE TABLE Test (id integer not null primary key, textdata nvarchar(500));";
const string create_table_sqlce = "CREATE TABLE Test (id integer not null identity primary key, textdata nvarchar(500));";
const string drop_table = "DROP TABLE Test";
const string insert_data = "INSERT INTO Test (textdata) VALUES ('{0}');";
const string read_data = "SELECT textdata FROM Test WHERE id = {0}";
const string update_data = "UPDATE Test SET textdata = '{1}' WHERE id = {0}";
const string delete_data = "DELETE FROM Test WHERE id = {0}";
public static void RunTests()
{
List<Results> results_list = new List<Results>();
for (int i = 0; i < 10; i++) {
results_list.Add(RunTest(DbType.Sqlite, false, false));
results_list.Add(RunTest(DbType.Sqlite, false, true));
results_list.Add(RunTest(DbType.Sqlite, true, false));
results_list.Add(RunTest(DbType.Sqlite, true, true));
results_list.Add(RunTest(DbType.Sqlce, false));
results_list.Add(RunTest(DbType.Sqlce, true));
}
foreach (var test_detail in results_list.GroupBy(r => r.test_details)) {
Console.WriteLine(test_detail.Key);
Console.WriteLine("Creating table: {0} ms", test_detail.Average(r => r.create_table_time));
Console.WriteLine("Inserting data: {0} ms", test_detail.Average(r => r.insert_time));
Console.WriteLine("Updating data: {0} ms", test_detail.Average(r => r.update_time));
Console.WriteLine("Selecting data: {0} ms", test_detail.Average(r => r.select_time));
Console.WriteLine("Deleting data: {0} ms", test_detail.Average(r => r.delete_time));
Console.WriteLine("Dropping table: {0} ms", test_detail.Average(r => r.drop_table_time));
Console.WriteLine();
}
}
static Results RunTest(DbType db_type, bool use_trx, bool use_wal = false)
{
DbConnection conn = null;
if (db_type == DbType.Sqlite)
conn = GetConnectionSqlite(use_wal);
else
conn = GetConnectionSqlce();
Results results = new Results();
results.test_details = string.Format("Testing: {0}, transactions: {1}, WAL: {2}", db_type, use_trx, use_wal);
results.create_table_time = CreateTable(conn, db_type);
results.insert_time = InsertTime(conn, use_trx);
results.update_time = UpdateTime(conn, use_trx);
results.select_time = SelectTime(conn, use_trx);
results.delete_time = DeleteTime(conn, use_trx);
results.drop_table_time = DropTableTime(conn);
conn.Close();
return results;
}
static DbConnection GetConnectionSqlite(bool use_wal)
{
SQLiteConnection conn = new SQLiteConnection("Data Source=sqlite.db");
if (!File.Exists(conn.Database))
SQLiteConnection.CreateFile("sqlite.db");
conn.Open();
if (use_wal) {
var command = conn.CreateCommand();
command.CommandText = "PRAGMA journal_mode=WAL";
command.ExecuteNonQuery();
}
return conn;
}
static DbConnection GetConnectionSqlce()
{
SqlCeConnection conn = new SqlCeConnection("Data Source=sqlce.sdf");
if (!File.Exists(conn.Database))
using (var sqlCeEngine = new SqlCeEngine("Data Source=sqlce.sdf"))
sqlCeEngine.CreateDatabase();
conn.Open();
return conn;
}
static long CreateTable(DbConnection con, DbType db_type)
{
Stopwatch sw = Stopwatch.StartNew();
var sqlcmd = con.CreateCommand();
if (db_type == DbType.Sqlite)
sqlcmd.CommandText = create_table_sqlite;
else
sqlcmd.CommandText = create_table_sqlce;
sqlcmd.ExecuteNonQuery();
return sw.ElapsedMilliseconds;
}
static long DropTableTime(DbConnection con)
{
Stopwatch sw = Stopwatch.StartNew();
var sqlcmd = con.CreateCommand();
sqlcmd.CommandText = drop_table;
sqlcmd.ExecuteNonQuery();
return sw.ElapsedMilliseconds;
}
static long InsertTime(DbConnection con, bool use_trx)
{
Stopwatch sw = Stopwatch.StartNew();
var sqlcmd = con.CreateCommand();
DbTransaction trx = null;
if (use_trx) {
trx = con.BeginTransaction();
sqlcmd.Transaction = trx;
}
for (int i = 0; i < NUMBER_OF_TESTS; i++) {
sqlcmd.CommandText = string.Format(insert_data, Guid.NewGuid().ToString());
sqlcmd.ExecuteNonQuery();
}
if (trx != null)
trx.Commit();
return sw.ElapsedMilliseconds;
}
static long SelectTime(DbConnection con, bool use_trx)
{
Stopwatch sw = Stopwatch.StartNew();
var sqlcmd = con.CreateCommand();
DbTransaction trx = null;
if (use_trx) {
trx = con.BeginTransaction();
sqlcmd.Transaction = trx;
}
Random rnd = new Random(DateTime.Now.Millisecond);
for (var max = NUMBER_OF_TESTS; max-- > 0; ) {
sqlcmd.CommandText = string.Format(read_data, rnd.Next(1, NUMBER_OF_TESTS - 1));
sqlcmd.ExecuteNonQuery();
}
if (trx != null)
trx.Commit();
return sw.ElapsedMilliseconds;
}
static long UpdateTime(DbConnection con, bool use_trx)
{
Stopwatch sw = Stopwatch.StartNew();
var sqlcmd = con.CreateCommand();
DbTransaction trx = null;
if (use_trx) {
trx = con.BeginTransaction();
sqlcmd.Transaction = trx;
}
Random rnd = new Random(DateTime.Now.Millisecond);
for (var max = NUMBER_OF_TESTS; max-- > 0; ) {
sqlcmd.CommandText = string.Format(update_data, rnd.Next(1, NUMBER_OF_TESTS - 1), Guid.NewGuid().ToString());
sqlcmd.ExecuteNonQuery();
}
if (trx != null)
trx.Commit();
return sw.ElapsedMilliseconds;
}
static long DeleteTime(DbConnection con, bool use_trx)
{
Stopwatch sw = Stopwatch.StartNew();
Random rnd = new Random(DateTime.Now.Millisecond);
var order = Enumerable.Range(1, NUMBER_OF_TESTS).ToArray<int>();
Action<int[], int, int> swap = (arr, a, b) => { int c = arr[a]; arr[a] = arr[b]; arr[b] = c; };
var sqlcmd = con.CreateCommand();
DbTransaction trx = null;
if (use_trx) {
trx = con.BeginTransaction();
sqlcmd.Transaction = trx;
}
// shuffling the array
for (var max = NUMBER_OF_TESTS; max-- > 0; ) swap(order, rnd.Next(0, NUMBER_OF_TESTS - 1), rnd.Next(0, NUMBER_OF_TESTS - 1));
foreach (int index in order) {
sqlcmd.CommandText = string.Format(delete_data, index);
sqlcmd.ExecuteNonQuery();
}
if (trx != null)
trx.Commit();
return sw.ElapsedMilliseconds;
}
}
以下是我得到的数字:
Testing: Sqlite, transactions: False, WAL: False
Creating table: 24.4 ms
Inserting data: 3084.7 ms
Updating data: 3147.8 ms
Selecting data: 30 ms
Deleting data: 3182.6 ms
Dropping table: 14.5 ms
Testing: Sqlite, transactions: False, WAL: True
Creating table: 2.3 ms
Inserting data: 14 ms
Updating data: 12.2 ms
Selecting data: 6.8 ms
Deleting data: 11.7 ms
Dropping table: 0 ms
Testing: Sqlite, transactions: True, WAL: False
Creating table: 13.5 ms
Inserting data: 20.3 ms
Updating data: 24.5 ms
Selecting data: 7.8 ms
Deleting data: 22.3 ms
Dropping table: 16.7 ms
Testing: Sqlite, transactions: True, WAL: True
Creating table: 3.2 ms
Inserting data: 5.8 ms
Updating data: 4.9 ms
Selecting data: 4.4 ms
Deleting data: 3.8 ms
Dropping table: 0 ms
Testing: Sqlce, transactions: False, WAL: False
Creating table: 2.8 ms
Inserting data: 24.4 ms
Updating data: 42.8 ms
Selecting data: 30.4 ms
Deleting data: 38.3 ms
Dropping table: 3.3 ms
Testing: Sqlce, transactions: True, WAL: False
Creating table: 2.1 ms
Inserting data: 24.6 ms
Updating data: 44.2 ms
Selecting data: 32 ms
Deleting data: 37.8 ms
Dropping table: 3.2 ms
使用sqlite进行200次插入或更新的时间~3秒可能看起来仍然有点高,但至少它比23秒更合理。相反,人们可能会担心SqlCe如何花费太少的时间来完成相同的200次插入或更新,尤其是因为在单个事务中使用每个SQL查询或在一个事务中一起使用时,似乎没有真正的速度差异。我不太了解SqlCe来解释这一点,但它让我担心。是否意味着当.Commit()返回时,您不确定更改是否实际写入磁盘?
答案 3 :(得分:5)
我最近使用SQL CE 4和NHibernate开展了一个项目,我发现性能非常好。使用SQL CE 4,我们能够在一秒钟内插入8000条记录。通过网络上的Oracle,我们每秒只能插入100条记录,甚至使用批量大小和seqhilo方法。
我没有测试它,但是查看一些针对.NET的NoSQL产品的性能报告,SQL CE 4似乎是独立应用程序的最佳解决方案之一。
只是避免使用Identity列,我们注意到如果不使用它们,性能会提高40倍。当Identity列用作PK时,相同的8000条记录需要40秒才能插入。