web-dev-qa-db-fra.com

Comparaison de performance SQL Server CE 4.0

SQL Server CE 4 (SQL Server Compact Edition 4.0) n'est pas déjà des nouvelles (si c'est le cas, vous pourriez lire cet article )

Mais il est très intéressant de voir la comparaison de performances SQL Server CE 4 à d'autres bases de données.

Surtout avec:

  • SQLite
  • SQL Server (1)
  • SQL Server Express *
  • peut-être firebird

(1) Pour les applications où la fonctionnalité est comparable.

Malheureusement, il n'y a pas tant de liens sur le sujet que Google fournit actuellement. En fait, je n'ai pas pu trouver (pour une version appropriée SQL CE).

Si on pouvait trouver ou partager de telles informations, le collecte ici pour l'humanité future.

37
MajesticRa

Voici mon article fraîchement préparé sur l'analyse comparative sur la page Web de CodeProject:

Benchmarking des performances de DB incorporé pour .NET: SQL CE 4.0 VS SQLite

(L'article a un statut en attente maintenant, vous devez être connecté sur CodeProject pour accéder à son contenu)

P.s: J'ai marqué par erreur ma réponse précédente en tant qu'entrée de wiki communautaire et n'obtiendrons aucune réputation. Cela m'a encouragé à écrire l'article pour - Projet de code sur ce sujet, avec un code quelque peu optimisé, plus d'informations supplémentaires sur les DBS intégrées et l'analyse statistique des résultats. Alors, s'il vous plaît, votez cette réponse si vous aimez l'article et ma deuxième réponse ici.

14
Alexander Galkin

Parce que je suis vraiment difficile avec les tests d'Alaudo, les résultats des tests et, finalement, avec sa conclusion, je suis allé de l'avant et j'ai joué un peu avec son programme et proposé une version modifiée.

Il teste chacun des 10 fois et génère les temps moyens:

  • sQLite sans transactions, à l'aide de jounal_mode par défaut
  • sqlite avec transactions, à l'aide de Journal_Mode par défaut
  • sQLite sans transactions, à l'aide de wal jounal_mode
  • sQLite avec transactions, utilisant WAL Journal_Mode
  • sqlce sans transactions
  • sqlce avec transactions

Voici le programme (c'est une classe en fait):

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;
    }
}

Voici les chiffres que je reçois:

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

~ 3 secondes pour 200 inserts ou mises à jour à l'aide de SQLite pourraient toujours sembler un peu élevé, mais au moins c'est plus raisonnable que 23 secondes. Inversement, on pourrait s'inquiéter de la manière dont SQLCE prend trop de temps pour compléter les 200 mêmes inserts ou mettre à jour, d'autant plus qu'il ne semble pas y avoir de différence de vitesse réelle entre chaque requête SQL dans des transactions individuelles, ou ensemble dans une transaction. Je ne sais pas assez sur Sqlce pour expliquer cela, mais cela m'inquiète. Serait-ce que cela signifie que lorsque .Commit () retourne, vous n'êtes pas assuré que les modifications sont réellement écrites sur le disque?

10
user610650