Pull to refresh

MongoDB vs MySQL (vs Cassandra): А теперь чуть более правильный ответ

Reading time 3 min
Views 27K
Собственно, сегодня был запощен топик "Сравниваем производительность MongoDB и MySQL на простом примере", в котором указывалось, что MongoDB превышает по производительности MySQL в разы. Хех, когда такое пишут — я сразу лезу проверять и сомневаться. Я полез в исходники оригинального теста (спасибо за публикацию). И как оказалось автор оригинального топика сделал ошибку в три символа и на самом деле не все так:
  1. В оригинале: MongoDB быстрее MySQL пишет в 1.5 раза (ДА, правда у меня в 3 раза)
  2. В оригинале: MongoDB быстрее MySQL читает в 10 раз (НЕТ, на самом деле — MongoDB примерно на равных плюс-минус 10-30%)
  3. InnoDB vs MyISAM — плюс-минус (в оригинале не тестировалось)
Сравнение здесь происходит только как key-value storage (запись-чтение по primary key).


На графике — число операций в секунду, (больше — лучше), шкала логарифмическая.
Последняя строка — то, что тестировал автор оригинального топика (неправильное, не в критику — все мы ошибаемся и учимся).


А теперь подробнее об ошибке...

Итак, ошибка оригинала была в том, что он делал SELECT так:

test.find({'_id':random.randrange(1, 999999)})

что возвращало Cursor(!), но не сам объект. То есть обращение к базе не происходит (или по крайней мере чтения данных не происходит). А вот что надо было:

test.find({'_id':random.randrange(1, 999999)})[0]

Если бы автор проверял бы, что сохраненное значение (INSERT) равняется вытащенному (SELECT) — такой ошибки не было бы.

В своем тесте я добавил assert, проверяющий что то, что сохранили — то же, что и читаем. И добавил сравнение с InnoDB (в комментах многие спорили, что может быть намного лучше). Настройки InnoDB дефолтовые.

Сам тест: по сути оба в качестве «key-value storage» (сохраняем по primary key + value, выбираем по primary key, читаем value). Да, сферический, да, в вакууме.

Да, внутри теста там есть вызовы assert и str. Разумеется они отжирают часть производительности, но для обоих тестов — их одинаковое число. А нам же просто СРАВНИТЬ производительность надо.

Больше результатов: Core2duo / WinXP SP3.



Больше 10000 записей тестировал — соотношение сохраняется. И вроде ни Mongo, ни MyISAM не сдуваются по скорости.

Исходник:
yoihj.ru/habr/mongo_vs_mysql.py

Я не говорю, что 100% прав (может и я в чем ошибся), так что проверяйте меня тоже.

P.S. Да, у меня выборка была последовательная, если же переключить ее на случайную (доставать каждый раз элемент со случайным номером) — ситуация меняется, но не кардинально, расположение сил все то же. Убедиться можно заменив в SELECTах i1 = str(i+1) на i1 = str(random.randint(1,cnt-1)+1).

В комментах fallen протестировал этим же кодом все под Linux + InnoDB_Plugin. Соотношение сил — примерно то же, но ровнее:

Linux + InnoDB_Plugin


«Core i7 920, 2GB RAM, Fedora 12 x64, mysql 5.1.44 + InnoDB 1.0.6 скомпилированные icc, mongodb 1.2.4 x64, sata диск обычный.»

Выводы:


  1. На запись MongoDB быстрее, если использовать как key-value storage;
  2. Чтение примерно одинаково происходит;
  3. Обе системы — вполне приличные, никто не устарел, никто никого не убил, явного проигрывающего нет.


vs Cassandra


И интереса ради добавлена Cassandra + pycassa (под win32) — сразу скажу — с ней у меня никакого опыта и много непонятного (.remove() не удаляет записи, а только очищает их, сами они остаются… + eventual consistency — оооооооочень трудно тестировать!) — полное прыгание с бубном в темноте, так что считайте просто развлекательным тестом.



import pycassa
client = pycassa.connect()
cf = pycassa.ColumnFamily(client, 'Keyspace1', 'Standard1')

# CASSANDRA INSERT
start_time = time.clock()
for i in xrange(cnt):
	i1 = str(i+1)
	cf.insert(i1, {'value': i1})
report('Cassandra INSERTs')

list(cf.get_range())

# CASSANDRA SELECT
start_time = time.clock()
for i in xrange(cnt):
	i1 = str(i+1)
	obj = cf.get(i1)['value']
	assert(obj == i1)
report('Cassandra SELECTs')



Йои Хаджи,
вид с Хабра
Tags:
Hubs:
+50
Comments 71
Comments Comments 71

Articles