Performance-Vergleich SQL Server Compact CE 4 mit Microsoft Access MDB

Bisher hatte ich noch keinen Performance-Vergleich zwischen SQL Server Compact 4 und Access (Jet) gefunden.

Deshalb habe ich quick-and-dirty mal ein bisschen was naives zusammen gebaut (siehe unten).

Hier die Ergebnisse:

1 x DELETE FROM Tabelle1:
- SQL CE: 00:00:00.1187228
- Access: 00:00:00.1891944

1 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}'):
- SQL CE: 00:00:00.0332512
- Access: 00:00:00.0804094

10 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}'):
- SQL CE: 00:00:00.3433201
- Access: 00:00:00.8424340

100 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}'):
- SQL CE: 00:00:03.5079310
- Access: 00:00:08.6798789

1000 x INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}'):
- SQL CE: 00:00:35.8964553
- Access: 00:01:19.2733553

1 x SELECT * FROM Tabelle1:
- SQL CE: 00:00:00.0447322
- Access: 00:00:00.0877710

10 x SELECT * FROM Tabelle1:
- SQL CE: 00:00:00.2697948
- Access: 00:00:00.6747978

100 x SELECT * FROM Tabelle1:
- SQL CE: 00:00:02.4612987
- Access: 00:00:07.9719581

1000 x SELECT * FROM Tabelle1:
- SQL CE: 00:00:26.1076206
- Access: 00:01:11.9598524

In allen Fällen, sowohl bei INSERT- als auch bei SELECT-Befehlen war SQL CE deutlich schneller.

({LOOPCTR} war meine Zählvariable in der Schleife)

Bitte beachtet, dass ich weder JOINs noch ORDER BYs und WHERE-Bedingungen verwendet habe. Damit kann das ggf. nochmals anders aussehen.

Der Quellcode:

internal static class Program
{
    private const string Folder = @"C:\Users\ukeim\Dropbox\Beruf\Prog\PerformanceMdbVsSqlCe\PerformanceMdbVsSqlCe";

    private static readonly string SqlCeConnectionString = $@"DataSource=""{Folder}\test.sdf""";

    private static readonly string MdbConnectionString =
        $@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""{Folder}\test.mdb""";

    private static void Main()
    {
        /*
        File.Delete($@"{Folder}\test.sdf");

        createDB();
        executeSqlCe(
            @"CREATE TABLE [Tabelle1] (
                [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
                Name1 NVARCHAR(255),
                Wert1 [int]
            )");
        */

        test1(1, @"DELETE FROM Tabelle1");

        test1(1, @"INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}')");
        test1(10, @"INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}')");
        test1(100, @"INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}')");
        test1(1000, @"INSERT INTO Tabelle1 (Name1, Wert1) VALUES ({LOOPCTR}, '{LOOPCTR}')");

        test1(1, @"SELECT * FROM Tabelle1");
        test1(10, @"SELECT * FROM Tabelle1");
        test1(100, @"SELECT * FROM Tabelle1");
        test1(1000, @"SELECT * FROM Tabelle1");
    }

    private static void test1(int rowCount, string sql)
    {
        var sw = new Stopwatch();

        // --

        Console.WriteLine(@"{0} x {1}:", rowCount, sql);

        sw.Start();
        for (var i = 0; i < rowCount; i++)
        {
            executeSqlCe(sql.Replace(@"{LOOPCTR}", i.ToString()));
        }
        sw.Stop();

        Console.WriteLine(@"- SQL CE: {0}", sw.Elapsed);

        // --

        sw.Start();
        for (var i = 0; i < rowCount; i++)
        {
            executeMdb(sql.Replace(@"{LOOPCTR}", i.ToString()));
        }
        sw.Stop();

        Console.WriteLine(@"- Access: {0}", sw.Elapsed);
        Console.WriteLine();
    }

    private static void createDB()
    {
        var en = new SqlCeEngine(SqlCeConnectionString);
        en.CreateDatabase();
    }

    private static DataTable executeSqlCe(string sql)
    {
        using (var conn = new SqlCeConnection(SqlCeConnectionString))
        using (var da = new SqlCeDataAdapter(sql, conn))
        {
            var table = new DataTable();
            da.Fill(table);

            return table;
        }
    }

    private static DataTable executeMdb(string sql)
    {
        using (var conn = new OleDbConnection(MdbConnectionString))
        using (var da = new OleDbDataAdapter(sql, conn))
        {
            var table = new DataTable();
            da.Fill(table);

            return table;
        }
    }
}

Siehe dazu auch meine ähnliche Frage auf Stack Overflow von 2011. Den gesamten Quelltext meines Programms habe ich jetzt auch auf Pastebin abgelegt.

Außerdem habe ich das ganze jetzt auch um SQLite-Unterstützung erweitert.

Ich habe jetzt noch ein paar JOIN/ORDER BY/WHERE eingebaut:

1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID:
- SQL CE: 00:00:00.0416608
- Access: 00:00:00.0822487

10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID:
- SQL CE: 00:00:00.3074814
- Access: 00:00:00.7083863

100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID:
- SQL CE: 00:00:03.1545674
- Access: 00:00:07.1357230

1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID ORDER BY a.ID:
- SQL CE: 00:00:32.6133773
- Access: 00:01:13.2414021

Sowie:

1 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID:
- SQL CE: 00:00:00.1236677
- Access: 00:00:00.1737928

10 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID:
- SQL CE: 00:00:00.3139946
- Access: 00:00:00.7289549

100 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID:
- SQL CE: 00:00:03.1246818
- Access: 00:00:07.1069451

1000 x SELECT a.* FROM Tabelle1 a LEFT JOIN Tabelle1 b ON a.ID=b.ID WHERE a.ID < 100 OR a.ID > 300 ORDER BY a.ID:
- SQL CE: 00:00:32.7180130
- Access: 00:01:13.9973234

Auch hier ist SQL CE immer noch deutlich schneller als MDB.