Статьи

MySQL против MongoDB: выбор решения для управления данными

1. Введение

Было бы справедливо сказать, что, как ИТ-специалисты, мы живем в золотой век эры управления данными. По мере того как наши программные системы становятся все более сложными и более распределенными, обусловленными множеством требований к масштабируемости и доступности, традиционные решения, используемые годами, стали отставать.

Цель этого учебного пособия — предоставить исчерпывающий обзор двух решений для управления данными: зрелой и широко используемой базы данных отношений, представленной MySQL, и нового блока MongoDB , который, в свою очередь, представляет хранилище данных нового поколения. Это ни в коем случае не битва с явным победителем в конце. Вместо этого, цель состоит в том, чтобы помочь разработчикам сделать выбор и найти правильное соответствие для своих приложений, рассмотрев функции MySQL и MongoDB , обсудив различные гарантии и ограничения, которые есть у каждого из них.

2. Доминирование систем RDBM

История и эволюция программного обеспечения для управления данными — не особенно интересная тема, на которую можно тратить время. В течение довольно долгого времени системы управления реляционными базами данных занимали лидирующие позиции, и в течение многих лет выбор был очевидным, MySQL , PostreSQL или Oracle , и это лишь некоторые из них. SQL (и его специфичные для вендора диалекты) был де-факто стандартом для запросов к хранилищам реляционных данных, и по определению каждый разработчик внутреннего программного обеспечения должен был изучить и понять хотя бы некоторые его основы. Он работал на удивление хорошо до недавнего времени, когда появилось целое семейство новых систем управления данными, явление, также известное как движение NoSQL (или не только SQL ).

3. Новая эра движения NoSQL

Проблемы, с которыми в настоящее время сталкиваются современные программные системы в отношении объемов данных и требований к пропускной способности запросов / транзакций, показали, что хранилища реляционных данных часто становятся узким местом, что накладывает ограничения на общую масштабируемость системы. Традиционно для решения этой проблемы была просто покупка более крупной коробки (так называемая вертикальная масштабируемость ), однако в какой-то момент цена за нее становится очень, очень высокой, что делает всю систему смехотворно дорогой и непрактичной.

Индустрия активно искала более дешевые способы создания сложных распределенных систем, используя вместо этого горизонтальную масштабируемость . Это также означало предложить альтернативы хранилищам реляционных данных, которые могли бы также масштабироваться горизонтально. Тот момент, когда началось NoSQL движение .

4. Таблицы против документов против графиков против ключа / значений

Реляционная модель данных представляет все данные в терминах кортежей и отношений (более известных как таблицы). Структурированные данные очень хорошо вписываются в эту модель, и долгое время не существовало другой жизнеспособной альтернативы. Благодаря движению NoSQL было разработано много альтернативных моделей данных, что дало начало целой группе специализированных систем хранения данных.

Решения NoSQL можно классифицировать в нескольких разных категориях. Хранилища данных документов предназначены для хранения, запросов и управления документами (полуструктурированные данные). Более зрелые представители этой категории включают CouchDB , Couchbase , MongoDB , OrientDB и HyperDex . Хранилища данных Key / Value предназначены для хранения, запроса и управления ассоциативными массивами (также известными как словари или хэши).

Наиболее широко используемые представители этой категории включают DynamoDB , FoundationDB , HyperDex , MemcacheDB , Redis , Riak , Aerospike и OrientDB . Хранилища графических данных предназначены для эффективного хранения и управления графическими структурами. Известные представители этой категории включают Neo4J , InfiniteGraph , GraphBase и OrientDB . И последнее, но не менее важное: хранилища данных с широкими столбцами используют гибридный подход (объединение некоторых характеристик хранилищ данных ключ / значение и традиционных хранилищ реляционных данных ). Наиболее продвинутыми представителями этой категории являются Accumulo , Cassandra и HBase .

Обратите внимание, что список различных хранилищ данных NoSQL, представленный выше, далеко не полон, он просто содержит наиболее известные и широко используемые имена, но их гораздо больше.

5. MySQL и MongoDB: сознательное решение

Достаточно вступления, поэтому давайте перейдем к более практичным вещам. В этой части руководства мы рассмотрим все аспекты процесса разработки приложений с использованием MySQL и MongoDB , а также уделим некоторое время обсуждению развертывания и мониторинга. Цель состоит в том, чтобы обсудить компромиссы и проектные решения, принимаемые каждым из этих хранилищ данных, и проанализировать, как они меняют способ разработки приложений. Кроме того, еще одна цель этого руководства — помочь в принятии решения, когда MongoDB может быть лучшим выбором, чем MySQL (и наоборот), принимая во внимание архитектуру приложения, шаблоны доступа к данным и требования к хранилищу.

Как мы уже сейчас, MongoDB является хранилищем данных документа. Он хранит документы в стиле JSON, которые группируются в коллекции. На вершине иерархии модели данных MongoDB находится база данных (пожалуйста, обратитесь к официальной документации , чтобы получить исчерпывающую информацию). Текущая готовая к выпуску версия MongoDB3.0.4 .

С другой стороны, MySQL — это реляционное хранилище данных. Данные хранятся в таблицах, которые содержат столбцы. Таблицы сгруппированы в базу данных (пожалуйста, обратитесь к официальной документации для получения подробной информации). Текущая готовая производственная версия MySQL5.6.25 .

MySQL поддерживает несколько механизмов хранения , каждый из которых предназначен для собственных целей и имеет некоторые функции, недоступные в других механизмах хранения. В этом уроке мы предполагаем, что используется механизм хранения InnoDB, так как он является стандартным и наиболее универсальным, который рекомендуется для использования, за исключением специализированных случаев использования.

5.1. Принудительная Схема против Схемы

MySQL как хранилище реляционных данных требует строгой схемы для своей модели данных: все таблицы должны создаваться с определенными столбцами. Только тогда данные могут храниться и запрашиваться с использованием языка SQL . Это несколько усложняет процесс разработки и развертывания, поскольку каждый раз, когда требуется модификация модели данных, сначала необходимо изменить схему, а затем перенести данные. Вот пример типичных шагов, необходимых для создания новой базы данных, новой таблицы и вставки в нее одной строки с использованием оболочки MySQL и языка SQL :

1
2
3
4
5
6
7
CREATE DATABASE tutorial;
USE tutorial;
CREATE TABLE chapters (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL
);
INSERT INTO chapters (title) VALUES ("MySQL and MongoDB: trade-offs, not battles");

В отличие от этого, MongoDB не накладывает никакой схемы на документы, хранящиеся в коллекции. Это становится обязанностью приложения, единственное, что ограничивает MongoDB — это поддерживаемые типы данных . Это значительно ускоряет процесс разработки, поскольку MongoDB можно сразу использовать для хранения документов JSON любой формы.

Структура документов может развиваться и изменяться с течением времени, и разные поколения документов могут сосуществовать в одной коллекции. Разработчик приложения должен решить, как выполнить очистку или миграцию данных, если это необходимо. Давайте посмотрим, как можно выполнить те же шаги по созданию новой базы данных, новой коллекции и вставке в нее одного документа с помощью оболочки MongoDB :

1
2
3
4
5
use tutorial
 
db.chapters.insert({
    "title": "MySQL and MongoDB: trade-offs, not battles"
})

Стоит отметить, что в следующей версии MySQL 5.7 (которая в настоящее время находится на этапе подготовки к выпуску) введена встроенная поддержка JSON. С введением этого нового типа данных JSON стало бы возможным объединить принудительную схему и данные без схемы в MySQL .

5.2. Нормализация против дублирования

Нормализация в мире реляционных баз данных — это процесс организации таблиц для минимизации избыточности данных. Он включает в себя разбиение таблицы на менее избыточные (и меньшие) таблицы без потери данных. Он также предполагает определение внешних ключей в старых таблицах, ссылающихся на первичные ключи новых. Например, это способ создания двух таблиц в MySQL , где таблица books ссылается на таблицу авторов :

01
02
03
04
05
06
07
08
09
10
11
12
CREATE TABLE authors (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL
);
CREATE TABLE books (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    author_id INT NOT NULL,
    FOREIGN KEY (author_id) REFERENCES authors(id)
);
INSERT INTO authors (name) VALUES ("Michael Kofler");
INSERT INTO books (title, author_id) VALUES ("The Definitive Guide to MySQL 5", 1);

Нормализация устарела для MongoDB . Вместо этого тщательное моделирование данных и определенный уровень дублирования данных — это способ извлечь максимальную пользу из хранилища данных документа. Приложение также несет ответственность за определение уровня повторения данных и синхронизацию всех фрагментов данных в случае изменений. Например:

1
2
3
4
5
6
db.books.insert( {
    "title": "The Definitive Guide to MySQL 5",
    "author": {
        "name": "Michael Kofler"
    }
})

5.3. Отношения против ссылок

В нормализованной базе данных предложение JOIN из SQL обычно используется для объединения записей из двух или более таблиц MySQL (есть и другие методы, но в целом они по существу приводят к одним и тем же результатам). Например:

1
SELECT * FROM books b INNER JOIN authors a ON a.id = b.author_id;

MongoDB поддерживает ссылки на документы, но не поддерживает объединения: для разрешения ссылки должен быть выполнен дополнительный запрос (или запросы) (что приводит к печально известной в реляционной среде проблеме запросов N + 1). Например, в приведенном ниже фрагменте мы вставляем ссылку на коллекцию авторов из коллекции книг вместо встраивания сведений об авторе:

01
02
03
04
05
06
07
08
09
10
11
db.authors.insert({
    "name": "Michael Kofler",
    "_id": 1 
})
db.books.insert({
    "title": "The Definitive Guide to MySQL 5",
    "author": {
        "$ref": "authors",
        "$id": 1
    }
})

Необходимые поездки туда и обратно — это цена, которую нужно заплатить за гибкость перехода без схемы. Однако, как мы уже упоминали в разделе « Нормализация против дублирования» , определенный уровень дублирования данных и тщательный анализ шаблонов доступа к данным могут смягчить проблему.

5.4. Транзакции против Атомных Обновлений

Транзакция — это логическая единица работы, выполняемая системой управления данными над своими данными. Важность транзакции заключена в ее фундаментальных свойствах: транзакция должна быть атомарной , последовательной , изолированной и долговечной (также известной как модель ACID ). MySQL — это хранилище данных о транзакционных отношениях, которое делает его идеальным выбором для критически важных приложений, которые не могут допустить потерю или несогласованность данных. Однако транзакции не являются бесплатными: они значительно ограничивают горизонтальную масштабируемость хранилищ данных, и MySQL не является исключением.

MongoDB не поддерживает транзакционные гарантии. Вместо этого он поддерживает атомарные обновления на уровне одного документа. Это означает, что когда одна операция обновления изменяет несколько документов, модификация каждого документа является атомарной, но операция в целом не является атомарной, и другие операции могут чередоваться. Стоит упомянуть, что можно реализовать транзакционную семантику поверх MongoDB (используя технику двухфазной фиксации ), но она требует довольно сложных реализаций.

5.5. SQL против JSON

SQL — это специальный язык программирования, предназначенный для управления данными, хранящимися в системе управления реляционными базами данных. Это единственный язык запросов, поддерживаемый MySQL , обогащенный несколькими расширениями для конкретного поставщика . Несмотря на свою простоту, SQL является очень мощным языком, который по существу состоит из двух частей: языка определения данных (DDL) и языка манипулирования данными (DML). Мы уже видели довольно много примеров, но давайте взглянем на самый простой и, вероятно, самый полезный пример выбора строк из таблицы:

1
2
SELECT * FROM books;
SELECT * FROM books WHERE title LIKE "%MySQL%";

В MongoDB все является документом, представленным в формате JSON. MongoDB не имеет специального языка для управления документами и использует совсем другой подход. Управление документами или запросы описываются с использованием очень богатого набора операторов , составленных друг с другом с использованием структуры JSON, как и любой другой документ. Это унифицированное представление достаточно мощное, выразительное и простое для понимания, плюс оно не требует изучения еще одного языка программирования. Большинство операторов интуитивно понятны и понятны, например:

1
2
3
4
5
6
db.books.find();
db.books.find({
    "title": {
        "$regex": "MySQL"
    }
});

5.6. Хранимые процедуры и сценарии

Хранимая процедура — это особая процедура, доступная на стороне сервера хранилища реляционных данных. Хранимые процедуры могут быть реализованы на разных языках программирования, однако большую часть времени они пишутся с использованием SQL или его специфичного для поставщика диалекта, как в случае с MySQL . Как правило, хранимые процедуры помогают повысить производительность приложений, выполняя некоторую логику непосредственно на сервере, требуя меньше информации для отправки между сервером и клиентом. Например, вот очень простая хранимая процедура MySQL :

1
2
3
4
5
6
7
8
9
DELIMITER //
CREATE PROCEDURE find_books
(IN pattern CHAR(255))
BEGIN
    SELECT COUNT(*) FROM books WHERE title LIKE pattern;
END //
DELIMITER ;
 
CALL find_books("%MySQL%");

MongoDB поддерживает сценарии на стороне сервера в форме выполнения кода JavaScript на сервере. Эти серверные сценарии могут напоминать хранимые процедуры, но реализация выходит за рамки простых сценариев, поскольку поддерживает парадигму сопоставления / сокращения , впервые заполняемую Google и широко применяемую для анализа больших данных. По сути, благодаря предоставлению сценария для команды map / lower становится возможным распараллеливать обработку больших и очень больших наборов данных во многих экземплярах хранилища данных MongoDB . Давайте посмотрим на очень наивный пример скрипта map / lower, который подсчитывает, сколько книг имеет строку «MySQL» в заголовке:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
db.runCommand( {
    mapReduce: "books",
    map: function() {
        if (this.title.indexOf("MySQL") >= 0) {
            emit("MySQL", 1);       
        }
    },
    reduce: function(key, counters) {
        count = 0;
 
        for (var index = 0; index < counters.length; ++index) {
            count += counters[index];                   
        }
 
        return count;
    },
    out: { inline: 1 }
} )

По сравнению с примером хранимой процедуры MySQL , MongoDB выглядит слишком многословно и сложно. Однако, как только концепции парадигмы « карта / уменьшение» станут более понятными, пример будет выглядеть довольно просто, открывая совершенно новую границу применения многих методов обработки, исследования и анализа данных.

5,7. GROUP BY против агрегатов

В области управления данными агрегатная функция — это функция, в которой значения нескольких записей данных группируются в зависимости от определенных критериев агрегации, как таковых, создавая одно значение более значимого значения или измерения. Язык SQL определяет набор конкретных предложений для выполнения агрегации: GROUP BY и HAVING . Набор стандартных группирующих функций среди многих других включает AVG () , COUNT () , MAX () , MIN () , STD () , SUM () . Давайте посмотрим на пример GROUP BY в оболочке MySQL :

01
02
03
04
05
06
07
08
09
10
11
CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    publisher VARCHAR(255) NOT NULL,
    product VARCHAR(255) NOT NULL,
    price NUMERIC (15,2) NOT NULL
);
INSERT INTO orders (product, publisher, price) VALUES
    ("The Definitive Guide to MySQL 5", "APress", 37.36),
    ("MySQL Cookbook", "O’Reilly", 49.65),
    ("Learning MySQL", "O’Reilly", 29.48);
SELECT publisher, SUM(price) FROM orders GROUP BY publisher;

MongoDB предлагает специализированный набор операций агрегации, которые обрабатывают документы и возвращают вычисленные (или агрегированные) результаты. Операции агрегации группируют значения из нескольких документов вместе и могут выполнять различные операции над сгруппированными данными для возврата одного результата. Агрегирование в MongoDB может быть выполнено двумя способами: с использованием конвейера агрегации или одноцелевых методов и команд агрегирования .

Давайте посмотрим на тот же пример, который мы подготовили для демонстрации агрегации MySQL , на этот раз с использованием конвейера агрегации MongoDB :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
db.books.insert( {
    "title": "The Definitive Guide to MySQL 5",
    "publisher": "APress",
    "price": 37.36
})
db.books.insert( {
    "title": "MySQL Cookbook",
    "publisher": "O’Reilly",
    "price": 49.65
})
db.books.insert( {
    "title": "Learning MySQL",
    "publisher": "O’Reilly",
    "price": 29.48
})
db.books.aggregate([
    { $match: {} },
    { $group: {
        "_id": "$publisher",
        "price": {
            "$sum": "$price"
        }
    }}
]);

Команда сопоставления / уменьшения, которую мы обсуждали в разделе « Хранимые процедуры и сценарии », также может рассматриваться как способ выполнения агрегации.

5,8. Кластеризация и разбиение / разбиение

В настоящее время объемы данных растут в геометрической прогрессии, и один физический экземпляр хранилища данных часто не способен сохранять и управлять такой массой данных в приемлемом темпе. Кластеризация — это технология, которая позволяет объединить множество отдельных вычислительных экземпляров для совместной работы. Что касается хранилищ данных, кластеризация идет бок о бок с разделением / разбиением данных, что является методом разделения большого количества данных между несколькими экземплярами хранилища данных.

В течение долгого времени MySQL был доступен в версии MySQL Cluster, которая претендует на то, чтобы быть масштабируемой в режиме реального времени ACID- совместимым хранилищем транзакционных данных. MySQL Cluster построен на основе распределенной многоузловой архитектуры, которая поддерживает автоматическое разделение / разбиение и масштабирование по горизонтали для обслуживания интенсивных операций чтения и записи.

Исторически сложилось, что MySQL Cluster выглядит слишком сложным, довольно сложным в настройке, мониторинге и обслуживании. В отличие от автономных развертываний MySQL , схема данных должна быть спроектирована таким образом, чтобы учитывать разделение / разбиение данных, иначе производительность хранилища данных сильно пострадает. Наконец, MySQL Cluster имеет много ограничений по сравнению с обычным дистрибутивом MySQL .

Хранилище данных документа MongoDB поддерживает сегментирование / разбиение из коробки, используя концепцию сегментированных кластеров . Сильной стороной шардинга / разбиения MongoDB является его простая и легкая настройка. Она довольно хорошо масштабируется по горизонтали, но следует учитывать несколько ограничений .

5.8.1. копирование

Репликация является важным методом обеспечения безопасности данных (путем репликации их во многих экземплярах хранилища данных) и во многих случаях для улучшения масштабируемости и отказоустойчивости приложений, работающих с этими данными. MySQL поддерживает традиционную репликацию master / slave , которая по умолчанию является асинхронной, но также возможны полусинхронные и отложенные режимы репликации.

MongoDB приближается к репликации, представляя наборы реплик. По сути, это репликация master / slave, но MongoDB использует немного другую терминологию. Ведущий, называемый первичным , получает все операции записи, а ведомые, называемые вторичными , применяют операции от первичного. Одной из лучших функций, поддерживаемых наборами реплик, является автоматическое переключение при сбое : когда первичный сервер не связывается с другими членами набора реплик, набор реплик будет пытаться выбрать другого члена, чтобы стать новым первичным.

Чтобы быть справедливым, можно настроить репликацию главного / подчиненного MySQL с автоматическим переключением при сбое, но есть некоторые проблемы и обсуждения по поводу этой функции в сообществе MySQL .

5.9. Полнотекстовый поиск

С давних пор MySQL поддерживает полнотекстовую индексацию и поиск, которые реализуются с использованием специального типа индекса. Важно отметить, что поддержка полнотекстовой индексации стала доступной для механизма хранения InnoDB только с момента выпуска MySQL 5.6 .

Интересно, что полнотекстовый поиск в MySQL возможен с использованием поиска на естественном языке (поиск по фразе), логического поиска (поиск по терминам), где слова для поиска могут быть помечены как «должны присутствовать» или «должны отсутствовать», а также расширение запроса поиск (небольшая модификация поиска на естественном языке). Однако в настоящее время полнотекстовая индексация не поддерживается в кластеризованных развертываниях MySQL (см. Раздел «Кластеризация и разделение / разбиение » для краткого обсуждения MySQL Cluster ). Давайте посмотрим на быстрый пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    product VARCHAR(255) NOT NULL,
    description VARCHAR(255) NOT NULL,
 
    FULLTEXT product_description (product, description)
);
INSERT INTO products (product, description) VALUES
    ("The Definitive Guide to MySQL 5", "This book shows readers how to connect to MySQL via all of the major APIs, including PHP, Perl, Java, JSP, and C#"),
    ("MySQL Cookbook", "Ideal for beginners and professional database and web developers"),
    ("Learning MySQL", "Book travels far into MySQL's subtleties, including complex queries and joins");
SELECT * FROM products
    WHERE MATCH (product, description)
    AGAINST ('database guide' IN NATURAL LANGUAGE MODE);

Поддержка полнотекстового поиска была введена в MongoDB не так давно. Как и в MySQL , он реализован с использованием специального типа индекса для содержимого строки (или массива строк). MongoDB также поддерживает поиск по фразе, поиск по терминам и логический поиск как их комбинации. Это простая в использовании и элегантно реализованная функция, но не без ограничений. К сожалению, в данный момент MongoDB не дает никакого контроля для указания подмножества полей для выполнения полнотекстового поиска: он всегда совпадает со всеми полями, включенными в полнотекстовый индекс. Давайте посмотрим на полнотекстовый поиск MongoDB в действии:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
db.products.insert({
    "product": "The Definitive Guide to MySQL 5",
    "description": "This book shows readers how to connect to MySQL via all of the major APIs, including PHP, Perl, Java, JSP, and C#"
})
db.products.insert({
    "product": "MySQL Cookbook",
    "description": "Ideal for beginners and professional database and web developers"
})
db.products.insert({
    "product": "Learning MySQL",
    "description": "Book travels far into MySQL's subtleties, including complex queries and joins"
})
db.products.createIndex({
    product: "text",
    description: "text"
})
db.products.find({
    $text: {
        $search: "database guide"
    }
})

5.10. развитие

Когда дело доходит до разработки, MySQL предоставляет широкий набор коннекторов, которые можно использовать для связи с сервером из большинства основных языков программирования по вашему выбору. Что касается разработки Java, MySQL включает драйвер JDBC, который соответствует спецификациям JDBC 3.0 и JDBC 4.0.

Хотя довольно редко можно встретить код, который использует прямые интерфейсы JDBC для связи с хранилищем реляционных данных (для этого было разработано много сред), полезно знать, что в этом участвует. Давайте посмотрим на следующий фрагмент кода, который подключается к MySQL и выполняет один оператор SELECT :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
try {
    connection = DriverManager.getConnection("jdbc:mysql://localhost/tutorial");
 
    Statement statement = null;
    ResultSet resultSet = null;
 
    try {
        statement = connection.createStatement();
        resultSet = statement.executeQuery("SELECT * FROM books");
                 
        while (resultSet.next()) {
            // Now do something with the ResultSet ....
        }
    } catch (SQLException ex) {
        // Log exception
    } finally {
        if (resultSet != null) {
        try { resultSet.close(); } catch ( SQLException ex) { /* ignore */ }
        }
 
        if (statement != null) {
        try { statement.close(); } catch ( SQLException ex) { /* ignore */ }
        }
    }
} catch (SQLException ex) {
    // Log exception
} finally {
    if (connection != null ) {
        try { connection.close(); } catch( SQLException ex ) { /* ignore */ }
    }
}

Это выглядит довольно многословно и полно обработки исключений. MongoDB, в свою очередь, имеет богатую экосистему драйверов , которая помимо основных языков включает драйверы для Erlang , Go , Node.js и Scala . Имея свободу в разработке собственных спецификаций, MongoDB находится в процессе разработки драйверов следующего поколения и быстро адаптирует существующие реализации к последним тенденциям в отрасли (хорошим примером этого является ReactiveMongo: Reactive Scala Driver для MongoDB ) ,

В качестве примера давайте рассмотрим один из способов подключения к MongoDB с использованием драйвера Java и Morphia (при условии, что у нас есть классы модели данных Book и Author):

1
2
3
4
5
6
7
final MongoClient client = new MongoClient( "localhost", 27017 );
final Datastore dataStore = morphia
    .map( Book.class, Author.class )
    .createDatastore( client, "tutorial" );
 
final Query< Book > query = dataStore.createQuery( Book.class ).
final List< Book > books =  query.asList();       

Исторически сложилось так, что поддержка JSON в Java была довольно хорошей из-за богатого набора библиотек, поддерживаемых сообществом, благодаря чему преобразование документов JSON в классы Java (и обратно) не представляло труда.

Было бы несправедливо не упомянуть, что сообщество Java разработало довольно много различных структур объектно-реляционного отображения ( ORM ) для абстрагирования от низкоуровневых интерфейсов JDBC, которые, по сути, позволяют писать код так же кратко, как пример MongoDB . Однако важно понимать, что они значительно усложняют существующие приложения.

5.10.1. развертывание

И MySQL, и MongoDB доступны в большинстве основных операционных систем. В большинстве случаев MySQL устанавливается из пакетов для конкретной платформы и требует привилегированного доступа к системе. Хотя загружаемые архивы также доступны, в зависимости от операционной системы, конфигурации и редакции (например, MySQL Cluster ), установка может быть довольно сложной и не интуитивно понятной (однако может не требовать привилегированного доступа к системе).

Наоборот, MongoDB в большинстве случаев распространяется в виде загружаемого архива, который можно сразу распаковать и использовать. Разумные значения по умолчанию играют здесь важную роль, требуя минимальной конфигурации, просто запустите сервер MongoDB и начните заполнять хранилище данных документами.

Будет справедливо отметить, что с контейнеризацией и Docker ландшафт процедур развертывания (к которому мы так привыкли) меняется очень быстро. Переход от традиционных дистрибутивов на основе пакетов к предварительно сконфигурированным контейнерам сводит воедино устанавливаемые пакеты и модели загрузки-распаковки-запуска: все становится образом, запускаемым как изолированный контейнер, доступным за миллисекунды.

Не говоря уже о том, что многие облачные провайдеры ( AWS , Cloud Foundry , Open Shift , и многие другие) имеют предложения программного обеспечения как услуги для MySQL и / или MongoDB , заботясь обо всех деталях конфигурации, инфраструктуры и масштабируемости.

5.11. Мониторинг и Диагностика

Очевидно, что мониторинг является критически важным компонентом любой процедуры администрирования хранилища данных. Существует множество коммерческих решений для мониторинга хранилища данных по вашему выбору, но давайте обсудим те, которые доступны как часть дистрибутивов MySQL и MongoDB .

MySQL имеет несколько способов выполнения мониторинга и диагностики. Прежде всего, это команда SHOW ENGINE <ENGINE> STATUS . Во-вторых, MySQL поддерживает схему производительности, которая является функцией для мониторинга выполнения сервера MySQL на низком уровне. И наконец, MySQL поддерживает датчики DTrace (не поддерживаемые каждой операционной системой), которые предназначены для предоставления информации о выполнении запросов на сервере MySQL и различных областях системы, используемых в этом процессе.

В дистрибутив MongoDB входит ряд утилит командной строки, которые позволяют быстро получать статистику о производительности и активности каждого экземпляра хранилища данных. Мало того, что каждый запущенный экземпляр MongoDB также предоставляет веб-интерфейс, который предоставляет диагностическую и контрольную информацию через простую веб-страницу. И, наконец, MongoDB включает в себя ряд команд для получения информации о состоянии базы данных путем подключения к ней через оболочку.

5,12. Безопасность

MySQL использует модель безопасности на основе привилегий. Основная функция системы привилегий MySQL состоит в том, чтобы аутентифицировать пользователя и связать этого пользователя с привилегиями в конкретной базе данных (такими как CREATE , DROP , SELECT , INSERT , UPDATE , DELETE и другие ).

На данный момент существует несколько вещей, которые не поддерживаются системой привилегий MySQL : невозможность явно указать, что данному пользователю должен быть запрещен доступ, и невозможность указать, что у пользователя есть права на создание или удаление таблиц в базе данных, но не на создание или удалите саму базу данных. На транспортном уровне MySQL поддерживает безопасные (зашифрованные) соединения между клиентами и сервером с использованием SSL (Secure Sockets Layer) с использованием протокола TLS v1.0.

Функции безопасности MongoDB включают аутентификацию, авторизацию и аудит. Его основой является управление доступом на основе ролей с гибким набором привилегий. Стоит отметить, что MongoDB обеспечивает основу для пользовательских ролей, определяя набор встроенных ролей. Также можно использовать TLS / SSL (Transport Layer Security / Secure Sockets Layer) для шифрования всего сетевого трафика MongoDB, чтобы гарантировать, что он будет доступен для чтения только предполагаемому клиенту.

5,13. Компромиссы, а не битвы

Как мы видели, MySQL и MongoDB служат одной общей цели: быть комплексным решением для управления данными для своих пользователей. Однако способы, которыми каждый из них подходит к этой цели, очень, очень разные. С одной стороны, мы видим довольно зрелое и проверенное хранилище реляционных данных. С другой стороны, мы встретили молодое, но быстро созревающее хранилище данных документов, подходящее для определенных классов современных веб-приложений.

Как уже несколько раз говорилось в этом уроке, это не битва, и мы не ищем победителя. Скорее, мы ищем решение, которое лучше соответствует потребностям ваших приложений. Более того, гетерогенная инфраструктура хранения данных в настоящее время становится скорее нормой, чем исключением: например, MongoDB может идеально соответствовать требованиям аналитики и отчетности, тогда как MySQL может хранить транзакции выставления счетов. К счастью, с помощью этого урока вы сможете выбрать подходящий инструмент для работы.

Во многих отношениях было бы справедливо сказать, что MongoDB был создан для веб-технологий: охват JSON, очень короткая кривая обучения, основа быстрого развития, новые функции добавляются в каждом выпуске. MySQL испытан в бою, консервативен и старомоден, однако ситуация меняется очень быстро, поскольку хранилища реляционных данных пытаются адаптироваться к потребностям современных приложений.

5,15. MySQL или MongoDB?

О MySQL и MongoDB уже много сказано. Было бы хорошо завершить обсуждение набором рекомендаций, когда MongoDB предпочтительнее, чем MySQL, и наоборот.

Прежде всего, если ваши данные имеют решающее значение для вашего бизнеса, очень вероятно, что MySQL является более безопасным выбором: свойства ACID существуют по определенной причине. Но каждое приложение отличается. Системы управления контентом, управление журналами, аналитика, форумы и блоги, хранилища событий, каталоги продуктов, управление запасами, приложения такого рода могут извлечь выгоду из MongoDB в качестве хранилища данных.

Модель данных без схемы является движущей силой для быстрой разработки: просто вводите новые свойства по мере необходимости, без необходимости выполнять эволюцию схемы и миграцию данных. Можно утверждать, что стиль обработки документов и выполнения запросов в MongoDB гораздо более удобен для разработчиков (более того, он не требует изучения какого-либо языка, например SQL ). Конфигурирование наборов реплик MongoDB и сегментированных кластеров действительно легко и быстро по сравнению с конфигурацией (и управлением) MySQL Cluster .

Современные архитектурные шаблоны способствуют разделению путей чтения и записи приложения (например, сегрегация ответственности команд и запросов или просто CQRS ). При этом приложения могут быть спроектированы таким образом, чтобы MySQL обрабатывал путь записи, но MongoDB мог бы быть хранилищем данных для пути чтения, где фрагменты данных объединялись в значимые документы.

5,16. MySQL и MongoDB: в наше время

Стоит отметить, что две компании, Twitter и Facebook , успешно эксплуатируют некоторые из крупнейших развертываний MySQL . Они с радостью делятся своим опытом, используя многочисленные посты в блоге: MySQL в Twitter , Еще один взгляд на MySQL в Twitter и инкубацию Mysos , Как Twitter хранит 250 миллионов твитов в день с использованием MySQL , WebScaleSQL: совместная работа, основанная на восходящем MySQL , и многое другое.

С другой стороны, внедрение MongoDB растет с каждым днем, и все больше и больше компаний внедряют его все больше и больше. Например, eBay поделился информацией о том, как мы создали первое приложение eBay Node.js , а Craigslist последовал за MongoDB на Craigslist: 1 год спустя . Без сомнения, мы увидим более широкое распространение в будущем.

6. Выводы

В этом коротком руководстве мы попытались взглянуть на два очень популярных хранилища данных: традиционную базу данных отношений, представленную MySQL, и хранилище данных документов, представленное MongoDB . Мы кратко рассмотрели наиболее важные функции и гарантии данных, которые есть у каждого из них, пытаясь оценить, как могут повлиять масштабируемость и доступность приложений. Мы пропустили много низкоуровневых внутренних деталей, так как MySQL и MongoDB стоят только нескольких книг. Вместо этого мы сделали обзор высокого уровня, выбирая самые интересные и важные области.