Neděle, květen 08, 2005

Test rychlosti Jet a SQLite

Pro jednu aplikaci potřebuji zvolit embeded způsob uložení dat a při rozhodování jsem nakonec skončil u dvou variant: Microsoft Jet, který je podle mnoha vývojářů zastaralý, nespolehlivý a konstruovaný nevhodně tak, aby mohl obsahovat i formuláře a o něco novější Open Source projekt SQLite. Open Source program by byl mému srdci bližší, ale měl bych se alespoň snažit řídit rozumem a proto jsem udělal pár testů, které měly tyto embeded způsoby ukládání dat porovnat.

Testování jsem prováděl na počítači s MS Windows XP Prof., SP2, Pentium 4 1.7, 512 MB RAM. Tyto údaje sice nepovažuji za důležité, ale přesto mohou být pro  někoho zajímavé. Důležité snad ani nejsou vlastní výsledky, ale poměr mezi dvěmi testovanými databázemi. Jako provider pro SQLite jsem zvolil ADO.NET 2.0 SQLite Data Provider, verze 1.0.8, vlastní SQLite byla verze 3.2.1. Vše běželo na Visual Studiu 2005 beta 2 a příslušném frameworku.

Určitě dostanu email, proč jsem také netestoval embeded verzi Firebirdu. To je sice nepochybně velmi kvalitní Open Source databáze, ale její embeded verze má bohužel jednu velmi podstatnou nevýhodu: umožňuje přístup k databázovému souboru v jednu chvíli pouze jednomu procesu/uživateli.

Test Jet SQLite
lokální síť lokální síť
Otevření databáze 0 31 0 31
10000x INSERT do tabulky bez indexu 55 750 67 218 1 657 343 1 516 875
10000x INSERT do tabulky s indexem 58 843 75 906 2 148 750 2 056 843
SELECT sloupec bez indexu 62 62 31 31
SELECT sloupec s indexem 31 0 0 0
SELECT LIKE 125 156 62 93

Komentáře k testu:

  • uvedené hodnoty jsou v ms;
  • testy jsem naprogramoval procedurálně - staticky, protože jsem byl líný přemýšlet nad objektovým návrhem;
  • všechny testy byly provedeny 5x a výsledná hodnota je průměrem z uvedených hodnot;
  • v době testování uložení dat na síťovém souborovém serveru (v tabulce označeno "síť") nebyl na síti žádný provoz, jediný, kdo v kanceláři byl jsem byl já a těch pár emailů co přicházelo z internetu na naši pomalé lince nic nemůže znamenat;
  • v databázi byla vždy jedna tabulka se 10000 vygenerovanými záznamy: CREATE TABLE t1(a INTEGER, b real, c VARCHAR(100));
  • k databázi jsem se připojoval pomocí OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=testik.mdb;" + "Jet OLEDB:Engine Type=5"), resp. SQLiteConnection("Data Source=testik.db");

Pár zajímavostí a komentářů

U Jet databáze testy plně na 100% vytížily CPU, disk téměř vůbec nepracoval. U SQLite byla situace přesně opačná, CPU vytížení bylo maximálně na 20% a naopak disk pracoval na plné obrátky. Práce s providerem OleDbConnection  si vyžádala běh dalších 12 podprocesů, u SQLiteConnection pracovalo 9 podprocesů. Konečná velikost databáze Jet s 10000 záznamy byla 39 MB, SQLite zabrala o mnoho méně, tj. 2.6MB. Ten rozdíl je opravdu závratný a z celého testu mě asi překvapil nejvíce i když ho nepovažuji za nijak důležitý.

Osobně se domnívám, že nízký výkon u příkazu INSERT u SQLite je zaviněn tím, že tato databáze si vynucuje okamžitý zápis na disk. Jet zřejmě využívá velkou cache, která se v tomto případě výrazně uplatní. Na druhé straně to může znamenat riziko porušení databázového souboru při HW nebo SW chybě.

Závěr

V případě, kdy potřebujete neustále provádět SQL příkaz INSERT, je Jet jednoznačnou volbou. Je v podstatě lhostejné, zda součástí tabulky je nějaký jednoduchý index nebo není. Složitější indexy jsem netestoval. Jet má jednu velkou nevýhodu a to je jeho nejistá budoucnost u Microsoftu. Mám lehké obavy, že dopadne jako FoxPro, které sice stále Microsoft prodává, ale udělal maximum, aby ho nikdo nepoužíval a přešel na Visual Basic a Jet. Nyní se historie opakuje a vývojáři jsou tlačeni přecházet na MSDE (Microsoft Data Engine). Někde jsem četl, že ten kdo historii zapomene nebo se z ní nepoučí, je odsouzen k tomu ji prožít znovu. To platí určitě i pro vývojáře software.

Co se týká výkonu, je z hlediska dotazů, což je podle mého 98% práce většiny databází, vítězem SQLite. Téměř dvojnásobný výkon je nevyvratitelným argumentem. Sám jsem překvapen. Očekával jsem, že největší a nejbohatší SW firma bude schopna za ta léta mít na trhu výkonnější produkt, než Public Domain výtvor (téměř) jednoho vývojáře.

3 komentářů:

Petr Mach řekl(a)...

Předpokládám, že u SQLite jste používal auto commit, takže každý insert byl commitnut, tj. byl vyžádán sync s diskem. To musí být velmi pomalé, protože diky jsou velmi pomalé, na rychlosti té databáze pak vlastně vůbec nezáleží, je to přehlušeno čakáním na zápis na disk. Otestoval jste tedy rychlost svého disku, ne SQLite. Kdybyste použil transakční zpracování a commitnul všechny inserty najednou, SQLite by se pronikavě zrychlila.

Anonymní řekl(a)...

Clanek o nicem. Myslenka dobra, ale jak spravne uvedl pisatel predemnou bez Bloku BEGIN; COMMIT; je to jen o testu rychlosti disku. Zkousel jsem neco podobneho a rozdil mezi metodou autora clanku - testovace pristupove doby pevneho disku a metody kdy se vsechny Inserty poslou databazi k sekvencimu zpracovani najednou je nesrovnatelna.

Martin řekl(a)...

Nevím zda jste u testu používal u SQLite pragma "synchronous", zajímavé by bylo použít všechny 3 módy. Týkají se právě onoho pomalého zápisu. Dovoluji si několik výňatků z dokumentace:

With synchronous OFF (0), SQLite continues without pausing as soon as it has handed data off to the operating system. If the application running SQLite crashes, the data will be safe, but the database might become corrupted if the operating system crashes or the computer loses power before that data has been written to the disk surface. On the other hand, some operations are as much as 50 or more times faster with synchronous OFF.

In SQLite version 2, the default value is NORMAL. For version 3, the default was changed to FULL.