Петр Зайцев показывает разницу между MySQL и MongoDB. Это расшифровка доклада с Highload++.
Вот если посмотреть такой известный Ranking, который называет DB-Engines то можно увидеть, что в течении многих лет популярность Open source баз данных она растет и коммерческих баз данных постепенно снижается.
Но что на самом деле, что еще более интересно, что если посмотреть на вот это отношение для разных типов баз данных, то видно, что для многих типов таких баз данных как колунарные базы данных, Time Series, Document stories у нас Open source базы данных наиболее популярны, только для более старых технологий таких как реляционные базы данных или еще более древние как Multivalue база данных. Мы видим, что коммерческие лицензии значительно более популярны.
Для многих приложений мы видим, что используют несколько баз данных для того, чтобы использовать их сильные стороны. Ни одна база данных не оптимизирована для всех всевозможных usecase’ов, даже если это PostgreSQL.
С одной стороны, это хороший выбор, с другой стороны нужно пытаться найти баланс, так как чем у нас есть больше разных технологий, тем сложнее нам их поддерживать, особенно если компания не очень большая.
Часто что видим, что люди приходят на такие конференции, слушают Facebook или Яндекс и говорят «ух ты! Сколько вот люди делают интересного. У них технологий разных используется штук 20 и еще штук 10 они написали сами», а потом они тот же самый подход пытаются использовать в своем стартапе из 10 человек, что работает разумеется не очень хорошо. Это как раз тот случай где размер имеет значение.
Подходы к архитектуре. Очень часто мы что видим? Что используется основное операционное хранилище и какие-то дополнительные сервисы. Например, для кеширования или полнотекстового поиска. Другой подход к архитектуре с использованием разных баз данных это то что используются микросервисы, где у каждого микросервиса может быть своя база данных, которая лучше оптимизирована для именно задач этого сервиса. Как пример, я говорил может быть основное хранилище на MySQL, Redis/Memcache используется для кеширования. Мы используем Elastic Search и родной Sphinx для поиска. И что-то вроде kafka может использоваться чтобы предавать данные в систему аналитики, которая часто делалась на чём-то вроде Hadoop.
Если мы говорим про основное операционное хранилище, наверное, у нас есть два выбора. С одной стороны, мы можем выбрать реляционные базы данных, с языком SQL, с другой стороны мы можем выбрать что-то нереляционное, дальше смотреть на подвиды, которые доступы в данном случае.
Если говорить про NoSQL модели данных, то их тоже достаточно много. Наиболее типичные это либо Key Value, либо Document, либо Wide Column базы данных. Примеры, Memcache, MongoDB, Cassandra соответственно.
Почему в данном случае мы сравниваем именно MySQL и MongoDB? На самом деле причин несколько. Во-первых, если посмотреть на Ranking баз данных, то мы видим, что MySQL, по этому рейтингу является наиболее популярной реляционной базой данных, а MongoDB это наиболее популярна нереляционная база данных. Поэтому их разумно сравнивать. С другой стороны, у меня есть наибольший опыт в использовании этих двух баз данных. Мы в Percona занимаемся плотно именно с ними, работает с многими клиентами, помогаем им сделать такой выбор.
Еще одна причина. Обе технологии изначально ориентированы на разработчиков простых приложений. Для тех людей, для которых PostgreSQL это слишком сложно.
Компания MongoDB изначально очень активно фокусировались на пользователях MySQL. Поэтому очень часто у людей есть опыт использования и есть выбор между этими двумя технологиями.
В Percona мы кроме того, что занимается поддержкой, консалтингом для этих технологий, у нас есть достаточно много написанного open source софта для обоих этих технологий.
На слайде можно посмотреть. Подробно я рассказывать об этом не буду.
Что следует обо мне лично, я занимаюсь MySQL значительно больше чем MongoDB, не смотря на то что я постараюсь предоставить сбалансированный обзор с моей стороны, у меня могут быть какие-то предрасположенности к MySQL, так как его тараканы я знаю лучше.
Выбор MySQL и MongoDB
Вот есть список разных вопросов, которые на мой взгляд имеет смысл рассматривать. Сейчас из них рассмотрим более детально.
Во-первых, что наиболее важно на мой взгляд, это знать какой есть опыт и предпочтения команды. На самом делать для многих задач подходят оба решения. Их можно сделать и так, и так, может быть несколько сложнее, может быть несколько проще. Но если у вас команда, которая долго работала с SQL базами данных и понимает реляционную алгебру и прочее, и часто их перетягивать и заставлять использовать нереляционные базы данных, таких как MongoDB, где нет даже полноценной транзакции может быть сложно. С другой стороны, если есть какая-то команда которые используют и хорошо знают MongoDB может быть SQL язык для них сложен и прочее, то наоборот. Так же имеет смысл рассматривать как оригинальную разработку, так и дальнейшее сопровождение, и администрирование поскольку обе они в итоге важны в цикле приложения.
Какие есть преимущества у данных систем?
Если говорить про MySQL. Это проверенная технология, понятно, что MySQL используется крупными компаниями более 15 лет. Есть возможность так как он использует стандарт SQL достаточной простой миграции на другие SQL базы данных если захочется. Есть возможность транзакций. Поддерживаются сложные запросы, включая аналитику и т.д.
С точки зрения MongoDB, здесь преимущество то что у нас гибкий JSON формат документов, для некоторых задач и некоторым разработчикам это им удобнее чем мучатся с добавлением колонок в SQL базах данных и т.д. не нужно учить SQL. Простые запросы, реже создают проблемы. Потому что, если посмотреть на проблемы производительности в основном они возникают, когда люди пишут сложные запросы с join в кучу таблиц и group by. Если такой функциональности в системе нет, то создать сложный запрос получается сложнее.
В MongoDB встроена достаточно простая масштабируемость с использованием технологии шардинга. Сложные запросы если возникают, мы их обычно решаем на стороне приложения. То есть, если нам нужно сделать что-то вроде join, мы можем сходить выбрать данные, потом сходить выбрать данные по ссылкам и потом их на стороне приложений обработать. Для людей, которые знают язык SQL это выглядит как-то убого и ненатурально. Но на самом деле многих разработчики application серверов для них это куда проще чем разбираться с join.
Следующий интересный момент.
Подход к разработке и жизненный цикл приложений
На самом деле если говорить про приложения, где используется MongoDB и на чём они фокусируются это очень быстрая разработка. Потому что всё можно постоянно можно менять, не нужно постоянно заботиться о строгом формате документа.
Второй момент, это конечно схема данных. Здесь нужно понимать, что у данных схема везде есть, нужно понять где она реализуется. Вы можете реализовывать схему данных у себя в приложении, потому что каким-то же образом вы эти данные используете, либо это схема реализуется на уровне базы данных. Очень часто если у вас есть какое-то приложение и с данными в базе данных работает только это приложение. Например, мы данные из этого приложения в эту базу данных сохраняем. На самом деле, схема на уровне приложения работает хорошо. Если у нас одни и те же данные используются многими приложениями, то часто это получается очень неудобно и сложно контролировать.
Здесь возникает так же вопрос время жизни приложения. С MongoDB хорошо делать приложения, у которых очень ограниченный цикл жизни. То есть если мы делаем приложение, которое живёт недолго, например, сайта для запуска фильма или олимпиада, мы пожили несколько месяцев после этого и это приложение практически не используется. Если приложение живёт дольше, то тут уже другой вопрос. Если говорить про распределение преимуществ и недостатки MySQL и MongoDB с точки зрения цикла разработки приложения, то их можно представить так:
С точки зрения модели данных. Модель данных очень сильно зависит от приложения и опыта команды. Сказать, что у нас реляционный или нереляционный подход к базам данных это было бы странно.
Если сравнивать их между собой, то понятно, что у нас есть. В MySQL это реляционная база данных, мы можем с помощью реляционной базы данных отображать связи между таблицами, нормализуя данные мы можем делать что изменения данных происходят атомарно в одном месте, на ненужно, когда данные у нас денормализованы при каких-то изменениях бежать и модифицировать кучу документов. Хорошо это или плохо? Результат у нас всегда это таблица, с одной стороны это просто, с другой некоторые структуры данных они на таблицу ложатся не хорошо и нам работать с этим неудобно.
Это всё в теории, если говорить о практическом использовании MySQL, мы тоже знаем, что мы часто денормализуем данные, с другой стороны для некоторые приложений мы используем что-то подобное, храним JSON или XML какие-то, другую структуру в колонках приложения.
У MongoDB у него структура данных основана на документах. Данные многих web приложений отображать очень просто, потому что если храним структуру, что-то вроде ассоциированный массив приложения, иерархические то это очень просто и понятно для разработчика сериализуется в JSON документ, как это всё раскладывать в реляционной базе данных по разным табличкам это может быть несколько нетривиально.
Результаты как список документов, у которых может быть совершенно разная структура он более гибок.
Как пример, если мы хотим сохранить Контакт лист с телефона. Понятно, что у есть данные которые хорошо кладутся в одну реляционную табличку: Фамилия, Имя и т.д. Если посмотреть на телефона или email адреса, то у одного человека их может быть несколько. Если нам это хранить в хорошем реляционном виде, то нам хорошо бы это хранить в отдельных таблицах, потом это всё собирать join’ом, что менее удобно, чем хранить это всё в одной коллекции, где хранятся иерархические документы.
Что следует здесь сказать. Это всё в строго реляционной теории, некоторые базы данных поддерживают массивы. В MySQL поддерживается формат JSON. В который можно засунуть несколько email адресов. Многие годы люди серилизовали это ручками, если надо нам сохранить несколько email адресов, то давайте запишем их через запятую и дальше приложение разберётся. Это не очень хорошо.
Термины
Термины интересно между MySQL и MongoDB и вообще между реляционными и нереляционными данными, что-то совпадает, что-то различается.
Например, в обоих случаях мы говорим об базах данных, но то что мы называем таблицей в реляционной базе данных, часто в реляционной называется коллекцией. То, что называется колонкой в MySQL, называется поле в MongoDB и т.д.
Что интересно с точки зрения использования join, в MongoDB нет такого же понятия, это понятие из реляционной структуры. Там мы либо делаем встроенный документ, что близко к концепту денормализации либо мы просто сохраняем идентификатор документа в каком-то поле и называем это ссылкой и дальше ручками выбираем данные которые нам нужны.
С точки зрения доступа, там, где мы к реляционным данным мы используем язык SQL, в MongoDB и многих других NoSQL базах данных используется такой стандарт как CRUD.
Этот стандарт говорит, что есть операции для создания, чтения, удаления, обновления документов.
Несколько примеров.
Как у нас могут наиболее типичные задачи по работе с документами могут выглядеть в MySQL и MongoDB:
Вот пример вставки.
Пример обновления.
Пример удаления.
На мой взгляд, когда у нас есть простейшие операции: поиск, вставка, они все работают достаточно хорошо. Когда речь идёт об более интересных операциях выборки, на мой взгляд, язык SQL куда более читаемый.
Что интересно, в данном случае если посмотреть на синтаксис, если вы разработчик, который знаком с языком javascript, то такой синтаксис, который предоставляет CRUD (MongoDB) для вас будет более естественным чем синтаксис SQL.
> вместо простого знака «>». Не очень читаемо на мой взгляд.
Достаточно легко с помощью интерфейса делать такие вещи как подсчёт числа строк числа в таблице или коллекции.
Но если мы делаем более сложные какие-то вещи, например, group by. В MongoDB для этого требуется использовать Aggregation framework, это несколько более сложный интерфейс, который показывает, как мы хотим отфильтровать, как мы хотим группировать и т.д. В Aggregation framework MongoDB уже поддерживает что-то вроде операции join.
Следующий момент. Это транзакции и консистентность (ACID). Если пойти и почитать документацию MongoDB, они скажут, что поддерживают ACID транзакции, но с ограничением.
На мой взгляд, стоит сказать, что ACID мы не поддерживаем, но поддерживаем другие минимальные нетранзакционные гарантии.
Какая у нас между ними разница?
Если говорить про MySQL, он поддерживает ACID транзакции произвольного размера, у нас есть атомарность этих транзакций, у нас есть мультиверсионность, можно выбирать уровень изоляции транзакций, который может начинать с read uncommitted и заканчивать serializable.
На самом дела, на уровне узла и репликацией мы можем конфигурировать как данные хранятся.
Мы можем сконфигурировать у InnoDB как работать с лог файлом, сохранять его на диск при комите транзакции или же делать это периодически. Мы можем сконфигурировать репликацию, включить, например, semi sync replication, когда у нас данные будут считаться сохранёнными только когда их копия будет на одном из slave’ов принята. С точки зрения MongoDB, MongoDB не поддерживают транзакции, но они поддерживают атомарные операции над документом, это значит, что с точки зрения одного документа у нас будет операция атомарна. Если у нас операция изменяет несколько документов и произойдет какой-то сбой внутри во время этой операции, то какие-то их этих документов могут быть изменены, а какие-то не изменены.
Консистентность, тоже самое делать на уровне документов и в кластере мы можем выбирать гибкую консистентность. Мы можем указать какие мы хотим гарантии, гарантии что у нас данные были записаны только на один узел или они были реплицированы на все на все узлы кластеров.
Чтение консистентности тоже происходит на уровне документа.
Есть такой вариант обновления, он называется isolated, который позволяет выполнить обновление изолированно от других транзакций, но он очень неэффективен, он переключает базы данных в монопольный режим доступа, поэтому он используется достаточно редко. На мой взгляд, если говорить о транзакции и консистентности в MongoDB она достаточна убогая.
Производительность
Производительность очень сложно сравнивать напрямую, потому что мы часто делаем разные схемы базы данных, дизайн приложения. Но если говорить в целом MongoDB изначально была сделана чтобы хорошо масштабироваться на много узлов через шардинг, поэтому эффективности было уделено меньше внимания.
Это результаты benchmark’a, который делал Mark Callaghan, он тоже будут выступать на этой конференции, будет рассказывать про Rocks ziib. Мы здесь видим, что с точки зрения использования процессора, использования ввода/вывода, то MySQL как InnoDB, так и MyRocks он использует значительно меньше процессора и дискового ввода/вывода на операции benchmark’a Linkbench, который использует Facebook.
Масштабируемость. Что такое масштабируемость в данном контексте?
Насколько легко нам взять наше маленькое приложение и масштабировать его на многих миллионы, может быть даже на миллиарды пользователей. Масштабируемость бывает разная. Она бывает средняя, в рамках одной машины, когда мы хотим поддерживать приложения среднего размера, либо масштабируемость на кластере, когда у нас приложения очень большие, понятно, что даже одна самая мощная машина не справится.
Так же имеет смысл говорить о масштабируемости с точки зрения, мы масштабируем чтение, мы масштабируем запись, мы масштабируем объем данных, в разных приложениях их приоритеты могут различаться, но в целом, если приложение очень больше обычно им приходиться работать со всеми из этих вещей.
С точки зрения MySQL, в новых версиях весьма хорошая масштабируемость в рамках одного узла для LTP нагрузок, если у нас маленькие транзакции, есть какая-нибудь железо в котором 64 процессора, то масштабируется достаточно хорошо. Аналитика или сложное запросы масштабируется плохо, потому что MySQL может использовать для одного запроса только одни поток, что конечно плохо.
Традиционно чтение в MySQL масштабируется с репликацией, запись и размер данных масштабируется через шардинг. Если смотреть на все большие компании, Facebook, Twitter они все используют шардинг. Традиционно шардинг в MySQL используется вручную. Есть некоторые framework для этого, например, vitess, это framework который google используется для scaling’a сервиса YouTube, они его выпустили в Open Source, до этого был framework Jetpants и т.д.
Стандартного решения для шардинга MySQL не предлагает, часто переход на шардинг требует внимания от разработчиков.
В MongoDB фокус изначально был в масштабируемости на многих узлах. Многим рекомендуется, даже если вы пока используете маленькое приложение, используется шардинг с самого начала. Может всего пару реплика сет, потом вы будете расти вместе со своим приложением.
В шардинге MongoDB есть некоторые ограничения, не все операторы с ним работают, например, есть isolated вариант для обеспечения консистентности. Она не работает если использовать шардинг. Но при этом многие основные операции они хорошо работают в шардингом, поэтому людям позволяется scale’ить приложения значительно лучше. На мой взгляд, шардинг и вообще репликация в MongoDB, она сделана лучше, чем MySQL, с точки зрения, что она значительна более проста в использовании для пользователя.
Администрирование
Администрирование – это все те вещи, о которых не думают разработчики, по крайне мере в первую очередь, то что нам приложение придётся бэкапить, обновлять версии, мониторинг, восстановление при сбоях и т.д.
MySQL достаточно гибок, у него есть много разных подходов. Есть хорошие Open Source реализации всего, но это множество вариантов порождает сложность. Я часто говорю с пользователями, которые только начинают изучать MySQL, они говорят, что очень много вариантов, одна репликация, какую мне использовать statement репликацию или raw репликацию, или mix? А еще есть gtid и стандартная репликация. Почему нельзя сказать просто работай?
В MongoDB всё больше ориентированно на то что оно работает одним стандартным образом, минимизация администрирования, но понятно, что это происходит при потере гибкости.
У комьюнити Open Source решений для MongoDB она тоже значительно меньше. Многие вещи в MongoDB достаточно жестко привязаны к Ops Manager с точки зрения рекомендаций. Ops Manager – это коммерческая разработка MongoDB.
Следующий момент.
Как в MongoDB, так и в MySQL есть мифы, которые были в прошлом, которые были исправлены. Но у людей длительная память, особенно есть что-то не работает. Помню в MySQL, после того как появились транзакции с InnoDB, люди лет 10 мне говорили, а в MySQL нет транзакций, тоже самое и здесь.
В MongoDB были много разных проблем с производительностью MMAP storage Engine, гигантские блокировки, неэффективное использование дискового пространства, сейчас стандартный движок WiredTiger многих уже не имеет. Имеет другие проблемы, но не эти.
Нет контроля схемы. Еще такой миф. В новых версиях MongoDB можно для каждой коллекции определять на JSON структуру, где данные будут валидироваться. Данные которые мы пытаемся вставить, и они не соответствуют какому-то формату их можно выкидывать.
Нет аналога join, тоже самое. В MongoDB это появилось, но нескольких ограниченных вещах. Только на уровне одного шарда и только если мы используем Aggregation framework, а не в стандартных запросах.
Какие у нас есть мифы в MySQL?
Здесь я буду говорить больше о поддержке NoMySQL решений в MySQL, об этом я буду говорить завтра.
Следует сказать, что MySQL сейчас тоже можно использовать через интерфейс CRUD’a, использовать в NoSQL режиме, примерно, как MongoDB.
Типичный пример, где используется MySQL решение, это сайт электронной коммерции. Когда у нас идёт вопрос о деньгах, часто мы хотим полноценные транзакции, консистентность. Для таких вещей хорошо подходит реляционная структура, которая была проработана и commerce на реляционных базах данных уже делался многие десятилетия, так что можно взять один из готовых подходов к структуре данных и использовать его.
Обычно с точки зрения e Commerce объем данных у нас не такой большой, так что даже достаточно большие магазины могут достаточно долго могут работать без шардинга.
Приложения у нас постоянно разрабатывается и усовершенствуется на протяжении многих лет и этого приложения много компонентов которые работают с одними и теми же данными. Кто-то рассчитывает, где цены поменять, кто-то ещё что-то делает.
Где часто используется MongoDB
Например, как бэкенд больших онлайн игр. Electronic Arts для очень многих игр используют MongoDB, почему?
Потому что масштабируемость очень важна. Если какая-то игра хорошо выстрелит, её приходиться часто масштабировать значительно больше чем предполагалось. С другой стороны, если не выстрелит, нам хотелось бы чтобы инфраструктуру можно было уменьшить. Во многих играх это идет так: мы запустили игру, у нее есть какой-то пик, приходиться делать большой кластер, потом игра уже выходит из популярности, для нее бэкенд нужно сжимать, сохранять и использовать. Используется в данном случае одно приложение (игра), база данных с одной стороны несложная, с другой стороны она по большому счету очень сильно привязана к приложению в которых хранятся все важные для игры параметры.
Часто консистентность базы данных на уровне объектов здесь достаточна, потому что много консистентости решается на уровне приложения. Например, что данные одного игрока сохраняет только один application service.
Дополнительная информация
Всем рекомендую это смешное видео
http://www.mongodb-is-web-scale.com/.
На этом мы закончим.
Доклад:
MySQL и MongoDB — когда что лучше использовать?
комментарии (85)