A napokban egy viszonylag speciális szemszögből azt vizsgáltam meg, hogy milyen adatbázis lehetőségeim vannak nagy mennyiségű adattárolásra. Azt mértem, hogy a Wikipédia magyar és angol változatának XML-ből adatbázisba áttöltése mennyi ideig tart, és mekkora a tárhelyigénye az így létrejövő adatbázisnak. A mérésben a MySQL 5.5 MyISAM és InnoDB táblaformátumai, illetve a MongoDB vettek részt. Eredmények, tapasztalatok. Update: az InnoDB sebességét más my.cnf beállításokkal is leteszteltem, s jóval kedvezőbb sebességet sikerült kihozni, illetve Percona Server 5.5.8 és MariaDB 5.2.4 szerverekkel is végeztem méréseket. Az eredményeket egy másik bejegyzésben hamarosan közzéteszem.

A célom annak eldöntése volt, hogy mely az az adattárolási eszköz, melyet kiválaszthatok nagyon-nagy mennyiségű adattárolásához. A legfontosabb szempont számomra az, hogy az adatokat minél gyorsabban letárolhassam, mivel folyamatosan fogok komoly mennyiségű változást átvezetni az adatbázison.
Az adatbázisszerver egy saját fordítású, MySQL 5.5.9-es community edition volt, a MongoDB pedig egy 1.6.5-ös, 64 bites bináris Linuxos verzió. A teszteket Ubuntu Linux alatt végeztem. A MySQL beállításai alapvetően a gyári “huge” alapján voltak belőve, a MongoDB-t nem konfiguráltam. A MySQL konfig releváns sorai:
key_buffer = 16M key_buffer_size = 384M max_allowed_packet = 16M table_open_cache = 512 sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M thread_stack = 192K thread_cache_size = 8 query_cache_limit = 1M query_cache_size = 32M thread_concurrency = 8 innodb_file_per_table innodb_file_format = Barracuda innodb_additional_mem_pool_size = 20M innodb_log_buffer_size = 8M innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 50
A teszteléshez a Wikipédia adatbázisát választottam, mind a magyar, mind az angol változat dumpjaival végeztem méréseket, de az angol akkora adatmennyiségnek bizonyult, hogy végülis nem futtattam le mindegyik mérést ezekkel az adatokkal. A magyar Wikipédia dump 336,707,547 byte-nyi bzippel tömörített XML fájl volt 415,111 szócikkel, amit egy rövid PHP kóddal dolgoztam fel, on-the-fly kitömörítéssel, és az adatok egyből történő letárolásával.
Több felállást is vizsgáltam, kipróbáltam az InnoDB transzparens tömörítési lehetőségét (ROW_FORMAT=COMPRESSED), illetve olyan felállást is, amikor a PHP oldalán tömörítettem be a Wikipédia cikkeket, a gzdeflate paranccsal. Az adatbázis id, language és content oszlopokat tartalmazott, ahol az id a cikk címe, a language a nyelve (‘hu’), míg a content a cikk tartalma volt. Egyetlen összetett index volt a táblákon, mely az id és language oszlopokat tartalmazta. A méréseket egy mást egyáltalán nem végző szerveren folytattam le, bőségesen elég memóriával, 7200 rpm-es SATA2 diszkekkel, négymagos Intel Xeon processzorokkal.
A következő mérési eredményeim voltak (táblatípus, tömörítés, időtartam perc:másodperc formában, az adatok helyfoglalása):
- MyISAM tábla, tömörítés nélkül: 5:14, 1,159,562K táblaméret
- MyISAM tábla, PHP oldalon gzdeflate-tel: 6:24, 531,764,518 byte táblaméret
- InnoDB tábla, tömörítés nélkül: 27:58, 2,138,120K táblaméret
- InnoDB tábla, PHP oldalon gzdeflate-tel: 18:14, 1,019,912K táblaméret
- InnoDB tábla, ROW_FORMAT=COMPRESSED-del: 22:42, 978,952K táblaméret
- MongoDB, tömörítés nélkül: 3:31, 4,144,128K táblaméret
- MongoDB, PHP oldalon gzdeflate-tel: 4:25, 2,048,000K táblaméret
- adattárolás nélkül: 2:28
MyISAM esetén az MYI, MYD és FRM fájlokat, InnoDB esetén az IBD és FRM fájlok, míg MongoDB esetén az adatbázishoz köthető .0, .1, .2… fájlok együttes méretét értem táblaméret alatt. Ez utóbbi méret csalóka lehet, mert a MongoDB nagyobb blokkokban foglalja le a tárhelyet az adatbázishoz.
Bármely megoldást is választottam, látszik, hogy az egyben bzippel tömörített, eredeti XML fájl mérete a legkisebb, ez várható is volt. Az InnoDB tárhelyigényét furcsállom, érdekes, hogy a tömörítés nélküli MyISAM volt akkora kb., mint a tömörített InnoDB. Az InnoDB beépített tömörítési lehetősége ami a sebességet illeti eléggé leszerepelt (de méretben sem sokkal jobb egy kliens oldali megoldásnál), továbbra is úgy tűnik, hogy kliens oldalon érdemesebb a tömörítést megoldani. Az InnoDB-nél látszik, hogy a sebesség erősen függ attól, hogy mekkora lesz a végleges táblaméret, a MyISAM tábláknál nem volt ilyen erős az összefüggés, sőt, amikor nem volt tömörítés, a több adatot gyorsabban ki tudta írni a MyISAM, itt már látszott, hogy a tömörítés fogta a sebességet, nem pedig az I/O műveletek.
A MongoDB verte mindegyik másik megoldás sebességben, a tárhely foglalása viszont láthatóan nem olyan optimális, mint egy MyISAM táblának, még talán úgy sem, hogy a lefoglalt blokk nagy része valószínűleg üres volt.
A sebessége miatt az InnoDB-t egyértelműen elvetettem. Míg MyISAM-mal 3-4 óra alatt betölthető volt az angol Wikipédia tartalom, addig az InnoDB-s táblába majd 1 napig tartott a betöltés. Az igen jelentős sebességkülönbség a fenti számokon is látszik. Azt gondolom, hogy a sebességen biztosan lehetne javítani pár konfig beállítás átállításával, de valószínűleg így is csak megközelítené, de nem érné be a MyISAM sebességét. A MongoDB megoldása továbbra is nagyon szimpatikusnak tűnik, a MongoDB vs. MyISAM kapcsán célszerű lenne egy random olvasási tesztet is elvégeznem, hogy korrekten tudjak dönteni.
A mérések csak az írási sebességet vizsgálták, és az írás 1 szálon zajlott, a forrás és a cél adatbázis ugyanazon a diszken volt, bár mind a kettő együttesen is belefért a memóriába, így valószínűleg az operációs rendszer cache-elte a forrást. Mivel ezek viszonylagosan speciálisnak mondhatóak, így mondjuk egy átlagos weblap esetén a működéssel valószínűleg nem összehasonlíthatók.