MyISAM, InnoDB és MongoDB tapasztalatok

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:141,159,562K táblaméret
  • MyISAM tábla, PHP oldalon gzdeflate-tel: 6:24531,764,518 byte táblaméret
  • InnoDB tábla, tömörítés nélkül: 27:582,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:42978,952K táblaméret
  • MongoDB, tömörítés nélkül: 3:314,144,128K táblaméret
  • MongoDB, PHP oldalon gzdeflate-tel: 4:252,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.

16 thoughts on “MyISAM, InnoDB és MongoDB tapasztalatok

  1. Bártházi András

    sgergely: Itt most teljesen másmilyen célokról van szó, mint egy CMS. Ott is megfontolnám a MyISAM vs. InnoDB méréseket, mert nem lenne egyértelmű a helyzet (pl. ha felhúzol egy cache réteget az egész elé egy nagyon látogatott site-on, akkor az olvasások száma minimalizálódhat a MySQL-ben).

    Zoli: Az ötlet jó, mindig is ki akartam próbálni, megpróbálom kiegészíteni a mérést a MariaDB-vel. Nem várnék tőle mást, mint a MyISAM-tól, de fogalmam sincs, hogy helyesek-e az elvárásaim.

  2. Tyrael

    szia, configure kapcsolok, illetve configok nelkul nem igazan lehet megmondani, hogy mennyire helytalloak az eredmenyek.
    ha megoldhato, hogy ezt kozzetedd, az sokat segitene, plusz altalaban meg a tetszscripteket is erdemes kozreadni, egyreszt ebbol kiderulhet, ha implementacios problema van, masreszt masok le tudjak ellenorizni, ossze tudjak hasonlitani az eredmenyeket.
    a default mysql configok kozismerten rosszak, a huge pl. 384M innodb_buffer_pool_size -t allit, amit dedikalt mysql szerver eseten a teljes elerheto memoria 60% kornyekere szokas allitani (amennyiben csak innodb tipusu tablakat hasznalunk)
    top, iotop, innotop alapjan meg azt is ki lehetett volna deriteni, hogy mi a szuk keresztmetszet, mysql eseteben kivancsi lettem volna ra, hogy mennyit valtozik a vegeredmeny, ha az indexeket az import vegen rakjuk csak ra a tablara, illetve ha eloszor csv-t generalunk az xml-bol, majd azt egyben nyalatjuk fel a mysql-lel, LOAD FROM INFILE segitsegevel.
    bar persze mivel nem elerheto az importalast vegzo script, ezert akar ott is lehettek problemak.

    kiprobalom valamelyik nap en is, kivancsi vagyok.
    http://download.wikimedia.org/huwiki/20110203/huwiki-20110203-pages-articles.xml.bz2
    gondolom ezzel jatszottal

    Tyrael

  3. Tyrael

    mariadb alatt pontositani kellene, hogy mit ertunk, az egy mysql fork, de eredetileg egy engine-nek indult, amit aztan atkeresztelt Monty Aria-ra, hogy ne legyen keveredes, hogy mikor beszelunk a rdbms-rol, mikor az engine-rol.
    a MariaDB az Aria-n kivul szallit meg tovabbi engine-eket, PBXT, XtraDB az ami ilyen altalanos celu engine.
    Aria erzesem szerint lassabb lesz, mint a myisam, kb. innodb-vel egy szinten.
    a durability meg az ACID pont azok a feature-ok, aminek a hianyaban egeszen gyors engine-t lehet csinalni. :)

    Tyrael

  4. sgergely

    András, én is épp arra akartam utalni, mint Tyrael, hogy a default beállítások nem biztos, hogy célra vezetnek a mérésben. Egyébként jó cikk, köszi :)

  5. Bártházi András

    Tyrael: Index nélkül megcsinálhatom a mérést, de nálam nem játszik az index nélküli működés, mert a célkörnyezet, amihez méréseket végzek, indexelt táblákat fog tartalmazni. Azaz számomra a feladat nem a Wikipédia cikkek betöltése, ez csak egy eszköz volt. A configure nem kapott semmilyen kapcsolót, a configot pedig nem véletlenül kivonatoltam a bejegyzésben, ott van. Vagy milyen további config érdekelne?

    Igen, azt a fájl dolgoztam fel. A feldolgozó kódom bzopen-nel nyitja meg a fájlt, strpos/substr kombinációkkal emeli ki belőle az elemeket, majd “REPLACE” paranccsal szúrja be az adatbázisba. MongoDB-nél is ún. “UPSERT”-et használok. Ezeken kívül azt hiszem mindent leírtam. A kódomat szívesen elküldöm, de nem szép, ezért nem tettem közzé. :)

    Az alternatív engine-eket majd ha eljutok odáig, hogy felrakjam, akkor leírom melyekkel kísérleteztem pontosan, minél többet kipróbálok, ha már. :)

  6. Bártházi András

    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.

  7. Zoli

    Tyrael!
    Igazad van, nem a legszerencsésebben fogalmaztam. Helyesebb lett volna azt írnom, hogy érdemes / érdekes lenne elvégezni a teszteket a MariaDB-ben lévő motorokkal is.

    Látom, közben András sem tétlenkedett. Ezer köszönet neki előre is!

  8. chx

    Valami hiba lesz a kréta körül, a MongoDB ennél lényegesen gyorsabb :) az írási sebessége tipikusan néhány tízezer rekord per másodperc… ha ennyit írsz akkor a syndelay paramétert érdemes tanulmányozni.

  9. Rol

    Myisam sebességben verhetetlen, de ha sok táblából szedjük össze az adatokat akkor hamar belassul …

    De ilyen mennyiségű adatnál miért nem postgresql?

  10. Bártházi András

    Rol: MyISAM-ot a MongoDB mindenképp veri, de úgy tapasztalom, hogy az InnoDB sem panaszkodhat ha korrektül be van állítva (épp mérem a sebességét, lesz következő bejegyzés). PostgreSQL-t nem a barátom, többször is nekifutottam pedig (de nézz körül, valamiért nem tartozik a hype-olt adatbázisok közé, pedig a funkciói alapján tartozhatna). A lényeg, hogy olyan megoldást semmiképp sem választok, melyet nem tartok praktikusnak, illetve amihez nem találok gyorsan fejlesztőt. Míg a MongoDB alapjairól az infókat egy _söralátéten_ átadom bárkinek félpercben, addig ez a PostgreSQL-nél nem áll fenn. MySQL-t pedig ugye “mindenki ismeri”. Kb. ezek miatt választottam ezeket az adatbázisokat tesztelésre.

  11. Pingback: MyISAM, InnoDB és MongoDB tapasztalatok II. at ‹Webakadémia /›

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>