Kilka miesięcy temu na rynku pojawił się nowy produkt w kategorii baz danych – MemSQL. Stworzony przez dwóch byłych deweloperów Facebooka, zaprojektowany ze znacznym naciskiem na wykorzystanie pamięci RAM, oraz konwertujący zapytania SQL do kodu C++. To wszystko przy deklarowanej 30-krotnie większej wydajności w porównaniu z bazą MySQL. Sprawdziliśmy czy faktycznie różnica jest tak ogromna oraz jak MemSQL sprawdza się w praktyce.

O MemSQL

MemSQL to baza danych, której głównymi atutami są minimalne wykorzystanie tradycyjnego dysku twardego kładąc przy tym duży nacisk na wykorzystanie pamięci RAM oraz konwersja (a później kompilacja) zapytań SQL do języka C++.  Jest dostępna w dwóch wersjach – darmowej deweloperskiej której ograniczenia to 10GB maksymalnej pojemności bazy danych oraz płatnej dla firm (dostępnej w 30 dniowej wersji trial). Aby ją pobrać należy wygenerować klucz licencyjny na stronie memsql.com oraz ściągnąć binarną paczkę dla 64 bitowych systemów GNU/Linux. Zalecana konfiguracja sprzętowa to wielordzeniowy CPU oraz co najmniej 8GB pamięci RAM.

MemSQL jest kompatybilny z aplikacjami wykorzystującymi MySQL, co oznacza że można bezproblemowo zaimportować dane z jednej bazy danych do drugiej, zmieniając jedynie port po którym łączy się aplikacja (domyślnie 3307). Twórcy zapewniają że MemSQL w pełni wspiera ACID (właściwości gwarantujące poprawne przeprowadzanie transakcji), oraz te same silniki bazodanowe co MySQL – InnoDB oraz MyISAM. Nie oznacza to jednak że MemSQL wspiera ten sam, pełny zestaw poleceń SQL co baza MySQL.

Jednym z czynników wpływających na deklarowaną wydajność jest przetrzymywanie wszystkich danych w ulotnej pamięci RAM. Narzuca to wymagania w postaci odpowiednio dużej ilości wolnej pamięci, co najmniej tak dużej co sama baza danych. Wszystkie zmiany zapisywane są w logu transakcji który znajduje się fizycznie na dysku. W przypadku awarii – dane są z niego odtwarzane, zapytanie po zapytaniu.

Kolejnym czynnikiem jest translacja zapytań SQL do C++ która odbywa się dla każdego nowopoznanego zapytania skierowanego do bazy. Polega to na wyłuskaniu z zapytania SQL jedynie głównej jego części z pominięciem wszelkich statycznych wartości.

Przykładowo zapytanie:
[sql]SELECT * FROM users WHERE col = 1;[/sql]
zostanie zinterpretowane jako
[sql]SELECT * FROM users WHERE col = @;[/sql]
a następnie skonwertowane do kodu C++ i skompilowane do postaci biblioteki współdzielonej (pliku .so). Efektem takiej operacji jest dłuższy czas wykonywania dla nowych zapytań, ale dużo szybszy dla następnych o podobnej konstrukcji.

Tyle teorii, w następnym kroku sprawdzimy jak te ulepszenia przekładają się na praktyczne rezultaty poddając je seriom testów.

Testy były wykonywane na serwerze opartym o system CentOS 6.3 w wersji 64 bitowej. Maszyna posiadała ośmiordzeniowy procesor Intel Core i7 930 taktowany 2.80 GHz oraz 8GB pamięci RAM. Użyte wersje oprogramowania to:

  • MySQL w wersji 5.5.25 (domyślna konfiguracja)
  • MySQL 5.5.25 z (zwiększona ilość pamięci dla MySQL, bufforów oraz cache)
  • MemSQL w wersji 1b (domyślna konfiguracja)

Do testów wykorzystano benchmark Sysbench (http://sysbench.sourceforge.net/) w wersji 0.3.1. Pierwszym etapem było zapełnienie bazy danych 1 000 000 (milionem) przykładowych rekordów. Wykorzystano w tym celu polecenie:
[sql]sysbench –test=oltp –db-driver=mysql –mysql-user=root –mysql-password=mysql –mysql-db=test –oltp-table-size=1000000 –myisam-max-rows=1000000 –mysql-table-engine=innodb –oltp-table-name=innodb prepare[/sql]
dla bazy MySQL oraz polecenie
[sql]sysbench –test=oltp –db-driver=mysql –mysql-user=root –mysql-host=127.0.0.1 –mysql-db=test –oltp-table-size=1000000 –myisam-max-rows=1000000 –mysql-table-engine=myisam –oltp-table-name=myisam  –oltp-dist-type=uniform prepare[/sql]
dla bazy MemSQL (oba w wersji dla InnoDB oraz MyISAM)

Do testów użyto dwóch trybów pracy Sysbench

  • Simple/read only  który polegał na wykonaniu 1 000 000 zapytań typu SELECT o różnym poziomie skomplikowania, nie modyfikując przy tym żadnych danych
  • Complex – będący złożonym trybem symulującym serię transakcji na które składało się 1 400 000 zapytań typu SELECT, 500 000 zapytań UPDATE/INSERT modyfikujących dane oraz 200 000 zapytań DELETE.

W przypadku silnika InnoDB transakcyjność osiągnięto przy użyciu standardowych poleceń BEGIN/COMMIT, dla MyISAM natomiast do symulowania transakcji Sysbench wykorzystuje polecenia LOCK TABLES/UNLOCK TABLES (co dość pokaźnie wpłynęło na wynik końcowy).

Poniżej wyniki testów w postaci wykresów oraz parametry użyte przy uruchomieniu każdego benchmarku. (prezentowany wynik to czas, jaki potrzebowała baza danych na ukończenie testu).

InnoDB zapytania typu select

[sql]–test=oltp –db-driver=mysql  –mysql-table-engine=innodb –num-threads=128 –oltp-table-size=1000000 –max-requests=1000000 –myisam-max-rows=1000000 –oltp-read-only=on  –oltp-test-mode=simple –oltp-dist-type=uniform –db-ps-mode=disable[/sql]

InnoDB transakcje

[sql]–test=oltp –db-driver=mysql  –mysql-table-engine=innodb –num-threads=128 –oltp-table-size=100000 –max-requests=100000 –myisam-max-rows=1000000 –oltp-read-only=off  –oltp-test-mode=complex –oltp-dist-type=uniform –db-ps-mode=disable[/sql]

MyISAM - zapytania typu SELECT

[sql]–test=oltp  –db-driver=mysql –mysql-table-engine=myisam –num-threads=128 –oltp-table-size=1000000 –max-requests=1000000 –myisam-max-rows=1000000 –oltp-read-only=on –oltp-test-mode=simple –oltp-dist-type=uniform –db-ps-mode=disable[/sql]

MyISAM - Transakcje

[sql]–test=oltp  –db-driver=mysql –mysql-table-engine=myisam –num-threads=128 –oltp-table-size=100000 –max-requests=100000 –myisam-max-rows=1000000 –oltp-read-only=off –oltp-test-mode=complex –oltp-dist-type=uniform –db-ps-mode=disable[/sql]

Jak widać, różnica w szybkości wykonywania zapytań jest znacząca. Nie jest to co prawda obiecywana 30-krotna różnica (w najlepszym wypadku kilkunastokrotna) ale mimo wszystko przewaga MemSQL jest ogromna. Jednak jako baza produkcyjna MemSQL jeszcze nie nadaje się według mnie do praktycznych zastosowań. Powodów ku temu jest kilka:

  1. Wciąż trwają prace nad ukończeniem pełnej specyfikacji SQL dla bazy danych MySQL. Wielu poleceń wciąż brakuje (np. TRUNCATE), brakuje obsługi widoków, triggerów czy kluczy obcych. Na obecną chwilę jedynym obsługiwanym zestawem znaków jest UTF-8.
  2. Nadal brakuje wparcia ze strony deweloperów dla bazy MemSQL. Próba instalacji oraz migracji aplikacji WordPress zakończyła się w naszym przypadku niepowodzeniem, czego powodem były zapewne niewspierane polecenia SQL wyeksportowane do pliku dump bazy danych. Na obecną chwilę istnieje oficjalny poradnik http://developers.memsql.com/docs/1c/guides/popular_tools.html o instalacji Django na MemSQL, lecz to wciąż zbyt mało, by można było mówić o pełnym wsparciu dla użytkowników.

Nie zmienia to faktu, iż MemSQL to produkt o ogromnym potencjale i ma sporą szansę aby zmienić obecną sytuację na rynku.

Poprzedni artykułOracle zamyka kod testów jednostkowych MySQL
Następny artykułHumble Bundle for Android 3

16 KOMENTARZE

  1. Zaraz. Jeżeli mam już rezerwować +8GB RAM, to dlaczego nie miałbym całej MySQL-owej bazy skopiować na ramdysk i używać jej stamtąd?

    • Podejrzewam że w przypadku MySQL na ramdysku gdyby doszło do awarii to mogło by dojść do utraty danych, chyba że by trzymać stan początkowy bazy oraz pisać binlogi na zwykły dysk to wtedy powinno się dać odtworzyć dane,

    • Ale wtedy czas startu bazy jest ogromnie duży. Zapis binlogów też niesie ze sobą jakiś narzut. Tak czy siak. Póki co MemSQL to zabawka co nie wspiera wielu typów danych, więc aplikacje na tym nie chodzą. Można co najwyzej odpalić na tym trzymanie sesji albo bazę z logami gdzie nie ma skompikowanej struktury.

    • dokładnie tak
      Mysql z silnikiem MEMORY przy padzie zasilania po prostu traci wszelkie dane, memsql jest na to odporny (kilkakrotnie ubijaliśmy bazę by sprawdzić jak to działa, mechanizm działa bez zarzutu a dane są w pełni zachowane).

  2. Lepszym rozwiązaniem byłoby to co ma MongoDB. Baza ta stara się wykorzystać jak najwięcej pamięci operacyjnej i potrafi ładować wszystko do pamięci powodując przyspieszenie działania. Jednak przy mniejszej ilości działa z dysku. W memSQL przekroczenie rozmiarów RAM przez dane w bazie spowoduje jej zatrzymanie.
    Samo memSQL na pewno znajdzie sporo zastosowań jak stanie się dojrzałe. Jednak moim zdaniem bazy relacyjne wymagają zmian koncepcyjnych, aby stały się nieco bardziej wydajne.
    PS. Świetny artykuł.

    • Niby tak, ale MongoDB jest bazą nierelacyjną, więc w wielu miejscach odpada jej użycie. No i brak transakcji, więc w wielu miejsach jej się nie używa. MongoDB jak i MemSQL to dobre wsparcie dla stabilnej i transakcyjnej bazy danych.

    • Nie maiłem na myśli zastępowania MySQL przez MongoDB :) Podoba mi się lepsze podejście do wykorzystania pamięci w MongoDB.
      Swoją drogą ciekaw jestem jak wyszłyby testy gdyby użyto MySQL z Memcachem.

  3. "Wciąż trwają prace nad ukończeniem pełnej specyfikacji SQL dla bazy danych MySQL. Wielu poleceń wciąż brakuje (np. TRUNCATE), brakuje obsługi widoków, triggerów czy kluczy obcych. Na obecną chwilę jedynym obsługiwanym zestawem znaków jest UTF-8."

    To co tutaj opisałeś nie jest żadną wadą, to tylko zalety.

    • brak funkcjonalnośći uznałem za wadę, jako że bez nich wiele aplikacji może zwyczajnie nie działać (a memsql ma być z założenia kompatybilny z mysql'em). Możesz opisac dlaczego uważasz je za zalety?

ZOSTAW ODPOWIEDŹ

Proszę wpisać swój komentarz!
Proszę podać swoje imię tutaj