Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Сравнение на производителността на SQL Server CE 4.0

Според мен е неправилно да се сравнява вградената база данни (като SQL CE) с релационна база данни от страна на сървъра (както всички останали, с изключение на SQLite и вградената версия на Firebird).

Основната разлика между тях е, че сървърните релационни бази данни с общо предназначение (като MS SQL, MySQL, Firebird Classic и SuperServer и т.н.) се инсталират като независима услуга и работят извън обхвата на основното ви приложение . Ето защо те могат да се представят много по-добре поради присъщата поддръжка за многоядрени и многопроцесорни архитектури, като използват функции на ОС като предварително кеширане, VSS и т.н., за да увеличат пропускателната способност в случай на интензивна работа с база данни и могат да изискват толкова памет, колкото вашата операционна система може да предостави една услуга/приложение. Това също означава, че показателите за ефективност за тях са повече или по-малко независими от вашето приложение, но до голяма степен зависят от вашия хардуер. В това отношение бих казал, че сървърните версии на всяка база данни винаги са по-производителни в сравнение с вградените.

SQL CE (заедно с Firebird Embedded, SQLite, TurboSQL и някои други) са вградени DB машини , което означава, че цялата база данни е пакетирана в един (или максимум 2) DLL-файла, които се разпространяват заедно с вашето приложение. Поради очевидните ограничения на размера (бихте ли искали да разпространявате 30 MB DLL заедно с вашето приложение с дължина 2-3 MB?) те също се изпълняват директно в контекста на вашето приложение и общата памет и производителност за операции за достъп до данни се споделят с други части на вашето приложение -- което се отнася както до наличната памет, процесорно време, пропускателна способност на диска и т.н. Наличието на нишки с интензивни изчисления, работещи успоредно с нишката ви за достъп до данни, може да доведе до драматично намаляване на производителността на вашата база данни.

Поради различните области на приложение, тези бази данни имат различна палитра от опции:server-db осигурява обширно управление на потребители и права, поддръжка за изгледи и съхранени процедури, докато вградената база данни обикновено няма поддръжка за управление на потребители и права и има ограничена поддръжка за изгледи и съхранени процедури (последните губят по-голямата част от предимствата си да работят от страната на сървъра). Пропускателната способност на данни е обичайно затруднение на RDBMS, сървърните версии обикновено се инсталират на ивици RAID томове, докато вградените DB често са ориентирани към паметта (опитайте се да запазите всички действителни данни в паметта) и минимизират операциите за достъп до съхранение на данни.

И така, това, което вероятно би имало смисъл, е да се сравнят различни вградени RDBMS за .Net за тяхната производителност, като 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();
        }


    }
}

Необходим отказ от отговорност:

  1. Получих тези резултати на моята машина:Dell Precision WorkStation T7400, оборудвана с 2 процесора Intel Xeon E5420 и 8 GB RAM, работеща с 64-битова Win7 Enterprise .
  2. Използвах настройките по подразбиране и за двете БД с низ за свързване „Източник на данни=име_на_файл_база_данни».
  3. Използвах най-новите версии както на SQL CE 4.0, така и на SQLite/System.Data.SQLite (от днес, 3 юни 2011 г.).

Ето резултатите за две различни проби:

> =Testing CRUD performance of embedded DBs=  
> => Samplesize: 200
> ==Testing SQLite== 
> Creating table: 396.0396 ms 
> Writing data: 22189.2187 ms 
> Updating data: 23591.3589 ms
> Reading data: 21.0021 ms 
> Deleting data: 20963.0961 ms 
> Dropping table: 85.0085 ms

> ==Testing SQL CE 4.0== 
> Creating table: 16.0016 ms 
> Writing data: 25.0025 ms 
> Updating data: 56.0056 ms 
> Reading data: 28.0028 ms 
> Deleting data: 53.0053 ms 
> Dropping table: 11.0011 ms

... и по-голяма извадка:

=Testing CRUD performance of embedded DBs=
 => Samplesize: 1000
==Testing SQLite==
Creating table: 93.0093 ms
Writing data: 116632.6621 ms
Updating data: 104967.4957 ms
Reading data: 134.0134 ms
Deleting data: 107666.7656 ms
Dropping table: 83.0083 ms

==Testing SQL CE 4.0==
Creating table: 16.0016 ms
Writing data: 128.0128 ms
Updating data: 307.0307 ms
Reading data: 164.0164 ms
Deleting data: 306.0306 ms
Dropping table: 13.0013 ms

Така че, както можете да видите, всички операции по писане (създаване, актуализиране, изтриване) изискват почти 1000 пъти повече време в SQLite в сравнение с SQLCE. Това не отразява непременно общото лошо представяне на тази база данни и може да се дължи на следното:

  1. Доставчикът на данни, който използвам за SQLite, е System.Data.SQLite , което е смесен сборник, съдържащ както управляван, така и неуправляван код (SQLite първоначално е написан изцяло на C и DLL осигурява само свързвания). Вероятно P/Invoke и маршалингът на данни изяждат голяма част от времето за операция.
  2. Най-вероятно SQLCE 4.0 кешира всички данни в паметта по подразбиране, докато SQLite изтрива повечето от промените в данните директно в дисковото хранилище всеки път, когато промяната се случи. Човек може да предостави стотици параметри за двете бази данни чрез низ за връзка и да ги настрои по подходящ начин.
  3. Използвах поредица от единични заявки, за да тествам базата данни. Поне SQLCE поддържа групови операции чрез специални .Net класове, които биха били по-подходящи тук. Ако SQLite ги поддържа също (съжалявам, не съм експерт тук и бързото ми търсене не даде нищо обещаващо), би било хубаво да ги сравните също.
  4. Наблюдавах много проблеми със SQLite на x64 машини (използващи същия .net адаптер):от неочаквано затваряне на връзката за данни до повреда на файла на базата данни. Предполагам, че има проблеми със стабилността или с адаптера за данни, или със самата библиотека.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. За да намерите следващия работен ден

  2. Как да получите резултат с плаваща стойност, като разделите две цели числа с помощта на T-SQL?

  3. Индексите на SQL Server - нарастващи или низходящи, каква разлика има?

  4. Възстановяване на SQL Server 2017

  5. Връщане на всички неизчислени колони от таблица в SQL Server