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

38

SQL Server CE 4 (SQL Server Compact Edition 4.0) уже не является новостью (если это так, вы можете прочитать эту статью)

Но очень интересно видеть сравнение производительности SQL Server CE 4 с другими базами данных.

Специально с:

  • SQLite
  • SQL Server (1)
  • SQL Server Express *
  • возможно, Firebird

(1) для приложений, где функциональность сопоставима.

К сожалению, не так много ссылок на тему, которую Google предоставляет прямо сейчас. На самом деле мне не удалось найти (для правильной версии SQL CE).

Если можно было бы найти или поделиться такой информацией, вы можете собрать ее здесь для будущего человечества.

  • 0
    Существует также еще один старый эталонный тест на Desktop Benchmark Roundup . Он использует C # провайдер для доступа к SQLite, так что если вы используете C напрямую, я думаю, это будет немного быстрее. Если вы запускаете свои собственные тесты, пожалуйста, опубликуйте результаты.
  • 3
    В чем вопрос?
Показать ещё 2 комментария
Теги:
sql-server
performance
sql-server-ce

4 ответа

15

На мой взгляд, неверно сравнивать встроенную базу данных (например, SQL CE) и серверную реляционную базу данных (как и все остальные, за исключением SQLite и Embedded версии Firebird).

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

SQL CE (наряду с Firebird Embedded, SQLite, TurboSQL и некоторыми другими) - это встроенные механизмы БД, что означает, что полная база данных упакована в один (или максимально 2) DLL файлы, которые распространяются вместе с вашим приложением. Из-за очевидных ограничений по размеру (хотите ли вы распространять 30 МБ DLL вместе с вашим 2-3-мегабайтным приложением?), Они также запускаются непосредственно в контексте вашего приложения, а общая < мощная > память и производительность для операций доступа к данным разделяются с другими частями вашего приложения, что касается как доступной памяти, так и времени процессора, пропускной способности диска и т.д. Имея интенсивный поток вычислений, выполняющийся параллельно с потоком доступа к данным может привести к резкому снижению производительности вашей базы данных.

В связи с различными областями применения эти базы данных имеют различную палитру опций: server-db обеспечивает расширенное пользовательское и правильное управление, поддержку представлений и хранимых процедур, тогда как встроенная база данных обычно не имеет никакой поддержки для пользователей и управления правами и ограничена поддержка просмотров и хранимых процедур (последние теряют большинство своих преимуществ от работы на стороне сервера). Пропускная способность данных является обычным узким местом РСУБД, серверные версии обычно устанавливаются на чередующиеся тома RAID, тогда как встроенные БД часто ориентированы на память (стараются сохранить все фактические данные в памяти) и минимизировать операции доступа к хранилищу данных.

Таким образом, вероятно, было бы сравнение различных встроенных 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();
        }


    }
}

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

  • Я получил эти результаты на своей машине: Dell Precision WorkStation T7400 оснащена 2 процессорами Intel Xeon E5420 и 8 ГБ оперативной памяти, работающими на 64-битной Win7 Enterprise.
  • Я использовал настройки по умолчанию для обеих БД со строкой подключения "Источник данных = имя_базы_файла".
  • Я использовал последние версии 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. Это не обязательно отражает общую плохую производительность этой базы данных и может быть вызвано следующим:

  • Поставщиком данных, который я использую для SQLite, является System.Data.SQLite, то есть смешанная сборка, содержащая как управляемый, так и неуправляемый код (SQLite изначально полностью написана на C, а DLL обеспечивает привязки). Вероятно, P/Invoke и маршалинг данных поглощает хорошую часть времени операции.
  • Скорее всего SQLCE 4.0 кэширует все данные в памяти по умолчанию, тогда как SQLite сбрасывает большую часть данных непосредственно на дисковое хранилище каждый раз, когда происходит изменение. Можно указать сотни параметров для обеих баз данных через строку подключения и соответствующим образом настроить их.
  • Я использовал серию одиночных запросов для тестирования БД. По крайней мере, SQLCE поддерживает массовые операции с помощью специальных классов .Net, которые были бы более подходящими здесь. Если SQLite тоже их поддерживает (извините, я не эксперт здесь, и мой быстрый поиск не дал ничего перспективного), было бы неплохо их сравнить.
  • Я заметил много проблем с SQLite на компьютерах x64 (с использованием того же .net-адаптера): из-за неожиданного закрытия подключения к повреждению файла базы данных. Я предполагаю, что есть некоторые проблемы с стабильностью либо с адаптером данных, либо с самой библиотекой.
  • 0
    Ой, я просто ошибся при редактировании своего поста и сделал это в записи сообщества вики. Жалко :(
  • 0
    Интересно, что SQLite обычно используется, так как в памяти хранится дБ и сбрасывает его относительно редко. Что бы вы попробовали в своих тестах с таким режимом использования SQLite?
Показать ещё 4 комментария
14

Вот моя свежеиспеченная статья о бенчмаркинге на веб-странице CodeProject:

Бенчмаркинг производительности встроенной базы данных для .Net: SQL CE 4.0 и SQLite

(теперь статья имеет статус ожидания, вам нужно войти в CodeProject для доступа к его контенту)

P.S.: Я ошибочно отметил свой предыдущий ответ в качестве вики-записи сообщества и не получаю никакой репутации. Это побудило меня написать статью для Code Project по этой теме, с несколько оптимизированным кодом, дополнительной информацией о встроенных dbs и статистическом анализе результатов. Итак, пожалуйста, проголосуйте за этот ответ, если вам нравится статья и мой второй ответ здесь.

  • 0
    Большое спасибо за то, что приложили усилия к тому, чтобы придумать эти тесты. Проблема здесь в том, что вы предоставляете цифры, которые вообще не имеют смысла; и затем вы позволите ему привести вас к ужасному выводу о том, как следует смотреть на ms sql ce поверх sqlite; это контрпродуктивно и раздражает. Пожалуйста, попробуйте исправить ваши тесты, прежде чем публиковать такие незаслуженные выводы.
  • 0
    Я только что посмотрел на ваш тест. У меня есть одна серьезная жалоба на это. Вы запускаете READ как ExecuteNonQuery. Однако, исходя из моего ограниченного опыта, наибольшая нагрузка на производительность чтения SQLite заключается в том, что каждый reader[int] вызывает P / Invokes в SQLite native. Это означает, что большие запросы будут очень медленными.
Показать ещё 1 комментарий
10

Потому что мне очень трудно провести тесты Alaudo, результаты тестов и, в конечном счете, с его заключением, я пошел вперед и немного поработал с его программой и придумал модифицированную версию.

Он проверяет каждый из следующих 10 раз и выводит среднее время:

  • sqlite без транзакций, используя jounal_mode по умолчанию
  • sqlite с транзакциями, используя default_log_name
  • sqlite без транзакций, используя WAL jounal_mode
  • sqlite с транзакциями, используя WAL journal_mode
  • sqlce без транзакций
  • sqlce с транзакциями

Вот программа (это класс на самом деле):

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

~ 3 секунды для 200 вставок или обновлений с использованием sqlite может показаться немного высоким, но, по крайней мере, более разумным, чем 23 секунды. И наоборот, можно беспокоиться о том, что SqlCe занимает слишком мало времени, чтобы выполнить те же 200 вложений или обновление, тем более, что, как представляется, нет реальной разницы в скорости между каждым SQL-запросом в отдельных транзакциях или вместе в одной транзакции. Я не знаю достаточно о SqlCe, чтобы объяснить это, но меня это беспокоит. Было ли это означать, что когда .Commit() вернется, вы не уверены, что изменения фактически записаны на диск?

  • 0
    Я сожалею, что у вас были трудные времена с моими результатами испытаний. Я не писал раньше, потому что я провожу исчерпывающие тесты обоих движков, пытаясь получить более реальную статистику. Помимо ваших вопросов о .Commit () - я думаю, что данные все еще кэшируются, завершенная транзакция означает только то, что данные изменяются атомарно, а не то, что данные должны быть изменены к концу .Commit () - я также заметил что вы получите лучшую разницу, если увеличите размер выборки (количество строк в каждом тесте) до 1000-2000-5000 строк. SQLite достигает действительно хорошей производительности.
5

Недавно я работал над проектом с использованием SQL CE 4 и NHibernate, и я нашел, что производительность действительно хорошая. С SQL CE 4 мы смогли вставить 8000 записей за секунду. С Oracle через сеть мы могли вставлять только 100 записей в секунду, даже размер партии, и были использованы подходы seqhilo.

Я не тестировал его, но рассматривая некоторые отчеты о производительности для продуктов NoSQL для .NET, SQL CE 4, по-видимому, является одним из лучших решений для автономных приложений.

Просто избегайте использования столбцов Identity, мы заметили, что производительность была в 40 раз лучше, если они не используются. Те же самые 8000 записей занимали 40 секунд для вставки, когда столбец Identity использовался как PK.

  • 0
    Действительно, столбцы идентичности были так плохи? Это может объяснить некоторые из проблем, которые я видел.
  • 1
    Отличный совет! Я работаю над проектом с SQL CE 4 и Fluent NHibernate, в котором мы получили ускорение вставки в 30 раз путем переключения с идентификаторов на первичные ключи hilo.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню