37 votes

Comparaison des performances de SQL Server CE 4.0

SQL Server CE 4 (SQL Server Compact Edition 4.0) n'est pas nouvelle déjà (Si elle est, vous pouvez lire cet article)

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

En particulier 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 tellement de liens sur le sujet que google propose maintenant. En fait, j'ai été incapable de trouver une (pour SQL correcte CE version).

Si l'on pouvait trouver ou partager ces informations permet de recueillir ici pour l'avenir de l'humanité.

16voto

Alexander Galkin Points 4312

À mon avis, il est incorrect de comparer la base de données intégrée (comme SQL CE) versus le côté serveur de base de données relationnelle (comme tout le reste, sauf pour SQLite et Intégré à la version de Firebird).

La principale différence entre eux est que l' usage général de serveur-côté relationnel des bases de données (MS SQL, MySQL, Firebird Classique et SuperServer etc.) sont installé en tant que service indépendant et exécuté en dehors de la portée de l'application principale. C'est pourquoi ils peuvent faire beaucoup mieux en raison de la valeur intrinsèque du support pour le multi-core et multi-architectures des processeurs, en utilisant les fonctionnalités du système d'exploitation comme pré-mise en cache, VSS, etc pour augmenter le débit dans le cas de l'intensif opération de base de données et peut prétendre à autant de mémoire que votre système d'exploitation peut fournir un seul service/de l'application. Cela signifie également que les indicateurs de performance sont plus ou moins indépendants à partir de votre application, mais en grande partie dépendre de votre matériel. À cet égard, je dirais que les versions serveur de base de données sont toujours plus de performances par rapport à ceux intégrés.

SQL CE (avec Firebird Embedded, SQLite, TurboSQL et quelques autres) sont incorporés moteurs de base de données, ce qui signifie que la base de données complète est emballé dans un seul (ou au maximum 2) DLL-fichiers qui sont distribués avec votre application. En raison de l'évidente les limites de la taille (aimeriez-vous avoir à les distribuer à 30 MO DLL avec votre 2 à 3 MO long de l'application?) ils ont également exécuter directement dans le contexte de votre application et le total de la mémoire et de performance pour les opérations d'accès aux données sont partagées avec d'autres parties de votre application -- qui concerne à la fois la mémoire disponible, le temps CPU, le débit du disque etc. Avoir un calcul intensif threads s'exécutant en parallèle avec vos données d'accès thread peut conduire à une diminution spectaculaire de votre base de données de performance.

En raison des différents domaines d'application de ces bases de données sont différentes palette d'options: serveur-db fournir un grand nombre d'utilisateur et de droit, de gestion, de soutien pour les vues et les procédures stockées, alors que la base de données intégrée, normalement, l'absence de toute assistance aux utilisateurs et la gestion des droits, et ont peu de soutien pour les vues et les procédures stockées (ceux-ci perdent la plupart de leurs avantages de la course sur le côté serveur). Le débit de données est une habitude des goulots d'étranglement des SGBD, serveur versions sont généralement installés sur les rayures des volumes RAID, alors que embedded DB sont souvent la mémoire orientée (essayez de garder toutes les données dans la mémoire) et de minimiser le stockage de données, les opérations d'accès.

Donc, ce qui ferait sens est probablement à comparer les différentes intégré SGBDR pour .Net pour leurs performances, comme MS SQL CE 4.0, SQLite, Firebird Embedded, TurboSQL. Je ne m'attends pas à des différences radicales au cours habituel de la période de l'opération, alors que certains de la base de données peut fournir un meilleur support pour les grandes Gouttes grâce à une meilleure intégration avec le système d'exploitation.

-- update --

Je dois reprendre mes dernières paroles, pour ma mise en œuvre rapide montre des résultats très intéressants.

J'ai écrit une application console pour tester les deux fournisseurs de données, voici le code source pour vous si vous voulez expérimenter avec eux sur votre propre.

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


    }
}

Nécessaire avertissement:

  1. J'ai eu ces résultats sur ma machine: station de travail Dell Precision T7400 équipé de 2 processeurs Intel Xeon E5420 Processeurs et de 8 go de RAM, fonctionnant 64bit Win7 Entreprise.
  2. J'ai utilisé les paramètres par défaut pour les deux bd avec "chaîne de connexion de Source de Données=database_file_name".
  3. J'ai utilisé les dernières versions de SQL CE 4.0 et SQLite/Système.Les données.SQLite (à partir d'aujourd'hui, le 3 juin 2011).

Voici les résultats pour les deux échantillons différents:

> =Test CRUD de la performance de l'embedded DBs= 
> => Samplesize: 200
> ==Test SQLite== 
> Création de la table: 396.0396 ms 
> L'écriture de données: ms 22189.2187 
> Mise à jour des données: ms 23591.3589
> La lecture des données: ms 21.0021 
> La suppression de données: ms 20963.0961 
> Abandon de la table: 85.0085 ms

> ==Test en SQL CE 4.0== 
> Création de la table: 16.0016 ms 
> L'écriture de données: ms 25.0025 
> Mise à jour des données: ms 56.0056 
> La lecture des données: ms 28.0028 
> La suppression de données: ms 53.0053 
> Abandon de la table: 11.0011 ms

... et un échantillon de plus grande taille:

=Test CRUD de la performance de l'embedded DBs=
 => Samplesize: 1000
==Test SQLite==
Création de la table: 93.0093 ms
L'écriture de données: ms 116632.6621
Mise à jour des données: ms 104967.4957
La lecture des données: ms 134.0134
La suppression de données: ms 107666.7656
Tomber de la table: 83.0083 ms

==Test en SQL CE 4.0==
Création de la table: 16.0016 ms
L'écriture de données: ms 128.0128
Mise à jour des données: ms 307.0307
La lecture des données: ms 164.0164
La suppression de données: ms 306.0306
Tomber de la table: 13.0013 ms

Donc, comme vous pouvez le voir, toute écriture des opérations (create, update, delete) nécessitent presque 1000x plus de temps dans SQLite par rapport à SQLCE. Il ne reflète pas nécessairement le général de mauvaise performance de cette base de données et peut-être pour les raisons suivantes:

  1. Le fournisseur de données que j'utilise pour SQLite est le Système.Les données.SQLite, qui est un mélange d'assemblage contenant à la fois réussi et le code non managé (SQLite est à l'origine entièrement écrite en C et la DLL fournit seulement des liaisons). Probablement P/Invoke et les données de marshaling mange un bon morceau de temps de fonctionnement.
  2. Le plus probable SQLCE 4.0 cache toutes les données en mémoire par défaut, tandis que SQLite bouffées de chaleur la plupart des modifications de données directement sur le disque de stockage à chaque fois que le changement se produit. On peut d'approvisionnement des centaines de paramètres pour les deux bases de données via une connexion en chaîne et de les ajuster de manière appropriée.
  3. J'ai utilisé une seule série de requêtes de test de la DB. Au moins SQLCE prend en charge en vrac par l'intermédiaire de spécial .Net des classes qui serait mieux adapté ici. Si SQLite soutient aussi (désolé, je ne suis pas un expert ici et ma recherche rapide a abouti à rien de prometteur) il serait bon de les comparer ainsi.
  4. J'ai observé beaucoup de problèmes avec SQLite sur les machines x64 (en utilisant les mêmes .net adaptateur): à partir des données de connexion étant fermée de manière inattendue à la base de données de la corruption de fichiers. Je suppose qu'il y a quelques problèmes de stabilité avec la carte de données ou avec la bibliothèque elle-même.

14voto

Alexander Galkin Points 4312

Voici mon fraîchement cuits article sur l'analyse comparative sur CodeProject page web:

L'analyse comparative de la performance de l'embedded DB pour .Net: SQL CE 4.0 vs SQLite

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

P. S.: j'ai malencontreusement marqué ma réponse précédente comme un wiki de la communauté d'entrée et de ne pas obtenir de toute la réputation pour elle. Cela m'a encouragé à écrire l'article pour le Projet de Code sur ce sujet, avec un peu de code optimisé, plus d'informations sur incorporé dbs et de l'analyse statistique des résultats. Donc, s'il vous plaît, votez cette réponse si vous aimez cet article et ma deuxième réponse ici.

5voto

ealbert Points 61

J'ai récemment travaillé sur un projet à l'aide de SQL CE 4 et NHibernate et j'ai trouvé la performance pour être vraiment bon. Avec SQL CE 4 nous avons été en mesure d'insérer 8000 enregistrements dans une seconde. Avec Oracle sur le réseau, nous n'avons pu insérer 100 enregistrements par seconde, même batch-size et seqhilo approches ont été utilisées.

Je n'ai pas tester, mais en regardant certains des rapports sur l'exécution des NoSQL produits pour .NET, SQL CE 4 semble être l'une des meilleures solutions pour des applications autonomes.

Juste éviter d'utiliser des colonnes d'Identité, nous avons remarqué que le rendement est de 40 fois mieux si ils ne sont pas utilisés. La même 8000 enregistrements ont été 40 secondes pour insérer lorsqu'une colonne d'Identité a été utilisé comme PK.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X