it-swarm.com.ru

Собственная поддержка JSON в MYSQL 5.7: каковы плюсы и минусы типа данных JSON в MYSQL?

В MySQL 5.7 был добавлен новый тип данных для хранения таблиц данные JSON в MySQL . Это, очевидно, будет большим изменением в MySQL. Они перечислили некоторые преимущества

Проверка документов - В столбце JSON могут храниться только действительные документы JSON, поэтому вы получаете автоматическую проверку ваших данных.

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

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

Удобство - Дополнительный встроенный синтаксис для столбцов JSON делает естественным объединение запросов Document в ваш SQL. Например (features.feature - это столбец JSON): SELECT feature->"$.properties.STREET" AS property_street FROM features WHERE id = 121254;

ВОТ ЭТО ДА ! они включают в себя некоторые замечательные функции. Теперь стало проще манипулировать данными. Теперь можно хранить более сложные данные в столбце. Таким образом, MySQL теперь приправлен NoSQL.

Теперь я могу представить запрос для данных JSON что-то вроде

SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN 
( 
SELECT JSON_EXTRACT(data,"$.inverted") 
FROM t1 | {"series": 3, "inverted": 8} 
WHERE JSON_EXTRACT(data,"$.inverted")<4 );

Так можно ли хранить огромные маленькие отношения в нескольких столбцах? Это хорошо? Это нарушает нормализацию. Если это возможно, то я думаю, что он будет действовать как NoSQL в столбце MySQL . Я действительно хочу узнать больше об этой функции. Плюсы и минусы типа данных MySQL JSON.

85
Imran
SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...

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

Заявление об "эффективном доступе" вводит в заблуждение. Это означает, что после того, как запрос исследует строку с документом JSON, он может извлечь поле, не анализируя текст синтаксиса JSON. Но для поиска строк все равно требуется сканирование таблицы. Другими словами, запрос должен проверять каждую строку.

По аналогии, если я ищу в телефонной книге людей с именем "Билл", мне все равно приходится читать каждую страницу в телефонной книге, даже если имена выделены, чтобы их было немного быстрее обнаружить.

MySQL 5.7 позволяет вам определить виртуальный столбец в таблице, а затем создать индекс для виртуального столбца.

ALTER TABLE t1
  ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
  ADD INDEX (series);

Затем, если вы запросите виртуальный столбец, он может использовать индекс и избежать сканирования таблицы.

SELECT * FROM t1
WHERE series IN ...

Или даже если вы запросите точное выражение, на котором основан виртуальный столбец (как в исходном запросе), он также может использовать индекс.

Это хорошо, но в нем не хватает смысла использования JSON. Привлекательной частью использования JSON является то, что он позволяет добавлять новые атрибуты без необходимости выполнять ALTER TABLE. Но оказывается, что вы все равно должны определить дополнительный (виртуальный) столбец, если хотите искать в полях JSON с помощью индекса.

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

SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>

Я бы вообще сказал, что это лучший способ использовать JSON в MySQL. Только в списке выбора.

Когда вы ссылаетесь на столбцы в других предложениях (WHERE, GROUP BY, HAVING, ORDER BY), эффективнее использовать обычные столбцы, а не поля в документах JSON.

Я представил доклад под названием Как использовать JSON в MySQL Wrong на конференции Percona Live в апреле 2018 года. Я обновлю и повторю доклад в Oracle Code One осенью.

Есть и другие проблемы с JSON. Например, в моих тестах требовалось в 2-3 раза больше места для хранения документов JSON по сравнению с обычными столбцами, хранящими те же данные.

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

Вы должны использовать JSON, когда JSON делает ваши запросы более эффективными.

Не выбирайте технологию только потому, что она новая или ради моды.

21
Bill Karwin

Следующее из MySQL 5.7 возвращает сексуальность с JSON звучит хорошо для меня:

Использование типа данных JSON в MySQL имеет два преимущества перед хранением строк JSON в текстовом поле:

Проверка данных. Документы JSON будут автоматически проверены, а недействительные документы приведут к ошибке. Улучшен формат внутреннего хранилища. Данные JSON преобразуются в формат, который обеспечивает быстрый доступ к данным в структурированном формате. Сервер может искать подобъекты или вложенные значения по ключу или индексу, обеспечивая дополнительную гибкость и производительность.

...

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

Обратите внимание на язык проверки документов , так как это важный фактор. Я полагаю, что необходимо провести ряд тестов для сравнения двух подходов. Эти два существа:

  1. Mysql с типами данных JSON
  2. Mysql без

На данный момент в сети есть только мелкие слайды на тему mysql/json/performance.

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

42
Drew

Недавно я столкнулся с этой проблемой и подытожил следующий опыт:

1, нет способа решить все вопросы. 2, вы должны использовать JSON правильно.

Один случай:

У меня есть таблица с именем: CustomField, и она должна содержать два столбца: name, fields. name - локализованная строка, ее содержимое должно выглядеть так:

{
  "en":"this is English name",
  "zh":"this is Chinese name"
   ...(other languages)
}

И fields должно быть так:

[
  {
    "filed1":"value",
    "filed2":"value"
    ...
  },
  {
    "filed1":"value",
    "filed2":"value"
    ...
  }
  ...
]

Как видите, и name, и fields можно сохранить как JSON, и это работает!

Однако, если я буду использовать name для очень частого поиска в этой таблице, что мне делать? Использовать JSON_CONTAINS, JSON_EXTRACT...? Очевидно, что не стоит больше сохранять его как JSON, мы должны сохранить его в независимой таблице: CustomFieldName.

Исходя из вышеизложенного, я думаю, вы должны помнить об этих идеях:

  1. Почему MYSQL поддерживает JSON?
  2. Почему вы хотите использовать JSON? Ваша бизнес-логика просто нуждалась в этом? Или есть что-то еще?
  3. Никогда не ленись

Спасибо

10
Bruce

По моему опыту, реализация JSON по крайней мере в MySql 5.7 не очень полезна из-за ее низкой производительности. Ну, это не так плохо для чтения данных и проверки. Однако модификация JSON в MySql в 10-20 раз медленнее, чем в Python или PHP. Давайте представим очень простой JSON:

{ "name": "value" }

Предположим, мы должны преобразовать это в нечто подобное:

{ "name": "value", "newName": "value" }

Вы можете создать простой сценарий с помощью Python или PHP, который будет выбирать все строки и обновлять их одну за другой. Вы не обязаны делать одну огромную транзакцию для нее, поэтому другие приложения могут использовать таблицу параллельно. Конечно, вы также можете сделать одну огромную транзакцию, если хотите, так что вы получите гарантию, что MySql будет выполнять "все или ничего", но другие приложения, скорее всего, не смогут использовать базу данных во время выполнения транзакции.

У меня 40 миллионов строк, и скрипт Python обновляет его за 3-4 часа.

Теперь у нас есть MySql JSON, поэтому нам больше не нужно Python или PHP, мы можем сделать что-то вроде этого:

UPDATE `JsonTable` SET `JsonColumn` = JSON_SET(`JsonColumn`, "newName", JSON_EXTRACT(`JsonColumn`, "name"))

Выглядит просто и отлично. Однако его скорость в 10-20 раз медленнее, чем версия Python, и это отдельная транзакция, поэтому другие приложения не могут изменять данные таблицы параллельно.

Итак, если мы хотим просто дублировать ключ JSON в таблице из 40 миллионов строк, нам не нужно использовать таблицу вообще в течение 30-40 часов. Это не имеет смысла.

Что касается чтения данных, из моего опыта прямой доступ к полю JSON через JSON_EXTRACT в WHERE также чрезвычайно медленный (намного медленнее, чем TEXT с LIKE в неиндексированном столбце). Виртуальные сгенерированные столбцы работают намного быстрее, однако, если мы заранее знаем нашу структуру данных, нам не нужен JSON, вместо этого мы можем использовать традиционные столбцы. Когда мы используем JSON, где это действительно полезно, я. е. когда структура данных неизвестна или часто меняется (например, пользовательские настройки плагина), создание виртуальных столбцов на регулярной основе для любых возможных новых столбцов не выглядит хорошей идеей.

Python и PHP делают проверку JSON как обаяние, поэтому сомнительно, нужна ли вообще проверка JSON на стороне MySql. Почему бы не проверить XML, документы Microsoft Office или проверить орфографию? ;)

4
Vitaliy