[mysql] MYSQL 5.7의 기본 JSON 지원 : MYSQL에서 JSON 데이터 유형의 장단점은 무엇입니까?

MySQL 5.7에서는 MySQL 테이블에 JSON 데이터 를 저장하기위한 새로운 데이터 유형 이 추가되었습니다. 분명히 MySQL에서 큰 변화가 될 것입니다. 몇 가지 이점을 나열했습니다.

문서 유효성 검사 -유효한 JSON 문서 만 JSON 열에 저장할 수 있으므로 데이터를 자동으로 유효성 검사 할 수 있습니다.

효율적인 액세스 -더 중요한 것은 JSON 문서를 JSON 열에 저장할 때 일반 텍스트 값으로 저장되지 않는다는 것입니다. 대신 최적화 된 이진 형식으로 저장되어 개체 구성원 및 배열 요소에 더 빠르게 액세스 할 수 있습니다.

성능 -JSON 열 내의 값에 대한 인덱스를 생성하여 쿼리 성능을 향상시킵니다. 이는 가상 열의 “기능적 인덱스”를 사용하여 달성 할 수 있습니다.

편리 성 -JSON 열에 대한 추가 인라인 구문은 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 );

그렇다면 소수의 json colum에 거대한 작은 관계를 저장할 수 있습니까? 좋은가요? 정규화를 중단합니까? 이것이 가능하면 MySQL 열에서 NoSQL처럼 작동 할 것이라고 생각합니다 . 이 기능에 대해 더 알고 싶습니다. MySQL JSON 데이터 유형의 장단점.



답변

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

이와 같은 식 또는 함수 내에서 열을 사용하면 쿼리를 최적화하는 데 도움이되는 인덱스를 사용하는 쿼리의 가능성이 사라집니다. 위에 표시된 쿼리는 강제로 테이블 스캔을 수행합니다.

“효율적인 액세스”에 대한 주장은 잘못된 것입니다. 이는 쿼리가 JSON 문서가있는 행을 검사 한 후 JSON 구문의 텍스트를 구문 분석하지 않고도 필드를 추출 할 수 있음을 의미합니다. 그러나 행을 검색하려면 여전히 테이블 스캔이 필요합니다. 즉, 쿼리는 모든 행을 검사해야합니다.

비유하자면, 이름이 “Bill”인 사람들을 전화 번호부에서 검색하는 경우 전화 번호부의 모든 페이지를 읽어야합니다. 비록 이름이 강조 표시되어있어 더 빨리 찾을 수 있습니다.

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>

일반적으로 이것이 MySQL에서 JSON을 사용하는 가장 좋은 방법이라고 말하고 싶습니다. 선택 목록에서만.

다른 절 (JOIN, WHERE, GROUP BY, HAVING, ORDER BY)의 열을 참조 할 때 JSON 문서 내의 필드가 아닌 기존 열을 사용하는 것이 더 효율적입니다.

2018 년 4 월 Percona Live 컨퍼런스에서 How to Use JSON in MySQL Wrong 이라는 강연을 발표했습니다 . 가을에 Oracle Code One에서 업데이트하고 반복 할 예정입니다.

JSON에는 다른 문제가 있습니다. 예를 들어, 내 테스트에서는 동일한 데이터를 저장하는 기존 열에 비해 JSON 문서를위한 저장 공간이 2-3 배 더 필요했습니다.

MySQL은 주로 MongoDB 로의 마이그레이션에 대해 사람들을 설득하기 위해 새로운 JSON 기능을 적극적으로 홍보하고 있습니다. 그러나 MongoDB와 같은 문서 지향 데이터 저장소는 기본적으로 데이터를 구성하는 비 관계형 방법입니다. 관계형과 다릅니다. 나는 하나가 다른 것보다 낫다고 말하는 것이 아니라 다른 유형의 쿼리에 적합한 다른 기술 일뿐입니다.

JSON이 쿼리를 더 효율적으로 만들 때 JSON을 사용하도록 선택해야합니다.

새로운 기술이나 패션을위한 기술을 선택하지 마십시오.


편집 : MySQL의 가상 열 구현은 WHERE 절이 가상 열 정의와 정확히 동일한 식을 사용하는 경우 인덱스를 사용하도록되어 있습니다. 즉, 가상 컬럼이 정의되어 있으므로 다음 가상 컬럼의 인덱스를 사용해야합니다.AS (JSON_EXTRACT(data,"$.series"))

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

이 기능을 테스트하여 표현식이 JSON 추출 기능인 경우 어떤 이유로 작동하지 않는다는 사실을 발견 한 경우를 제외하고는. JSON 함수가 아닌 다른 유형의 표현식에서 작동합니다.


답변

MySQL 5.7 의 다음은 JSON 사운드로 섹시하게 돌아 왔습니다 .

MySQL에서 JSON 데이터 유형을 사용하면 텍스트 필드에 JSON 문자열을 저장하는 것보다 두 가지 이점이 있습니다.

데이터 유효성 검사. JSON 문서는 자동으로 검증되고 유효하지 않은 문서는 오류를 생성합니다. 내부 저장소 형식이 개선되었습니다. JSON 데이터는 구조화 된 형식의 데이터에 대한 빠른 읽기 액세스를 허용하는 형식으로 변환됩니다. 서버는 키 또는 인덱스별로 하위 객체 또는 중첩 된 값을 조회 할 수 있으므로 유연성과 성능이 향상됩니다.

전문화 된 NoSQL 저장소 (문서 DB, 키-값 저장소 및 그래프 DB)가 특정 사용 사례에 더 적합한 옵션 일 수 있지만이 데이터 유형을 추가하면 기술 스택의 복잡성을 줄일 수 있습니다. 가격은 MySQL (또는 호환 가능) 데이터베이스와 결합됩니다. 그러나 이는 많은 사용자에게 문제가되지 않습니다.

문서 유효성 검사 에 대한 언어 는 중요한 요소이므로 유의하십시오 . 두 가지 접근법을 비교하기 위해 일련의 테스트를 수행해야한다고 생각합니다. 그 두 가지는 :

  1. JSON 데이터 유형이있는 MySQL
  2. 없는 MySQL

인터넷은 내가보고있는 것에서 mysql / json / performance 주제에 대해 얕은 슬라이드 공유를 가지고 있습니다.

아마도 귀하의 게시물이 허브가 될 수 있습니다. 또는 성능은 나중에 생각하고 확실하지 않으며 테이블을 여러 개 만들지 않아서 기뻐할 수도 있습니다.


답변

최근에이 문제가 발생했으며 다음 경험을 요약했습니다.

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와는 fieldsJSON으로 저장 될 수 있으며, 작동!

그러나를 사용 name하여이 테이블을 자주 검색하는 경우 어떻게해야합니까? 를 사용하여 JSON_CONTAINS, JSON_EXTRACT…? 분명히 더 이상 JSON으로 저장하는 것은 좋지 않습니다 CustomFieldName. 독립 테이블에 저장해야합니다 ..

위의 경우에서 다음 아이디어를 염두에 두어야한다고 생각합니다.

  1. MYSQL이 JSON을 지원하는 이유는 무엇입니까?
  2. JSON을 사용하는 이유는 무엇입니까? 귀하의 비즈니스 로직에 이것이 필요합니까? 아니면 다른 것이 있습니까?
  3. 게으르지 마십시오

감사


답변

내 경험상, 적어도 MySql 5.7의 JSON 구현은 성능이 좋지 않아 그다지 유용하지 않습니다. 글쎄, 데이터를 읽고 유효성을 검사하는 것은 그렇게 나쁘지 않습니다. 그러나 JSON 수정은 Python 또는 PHP보다 MySql에서 10-20 배 느립니다. 매우 간단한 JSON을 상상해 보겠습니다.

{ "name": "value" }

다음과 같이 변환해야한다고 가정 해 보겠습니다.

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

모든 행을 선택하고 하나씩 업데이트하는 Python 또는 PHP로 간단한 스크립트를 만들 수 있습니다. 하나의 큰 트랜잭션을 만들지 않아도되므로 다른 응용 프로그램에서 테이블을 병렬로 사용할 수 있습니다. 물론 원하는 경우 하나의 거대한 트랜잭션을 만들 수도 있으므로 MySql이 “모두 또는 아무것도 수행하지 않음”을 보장 할 수 있지만 다른 응용 프로그램은 트랜잭션 실행 중에 데이터베이스를 사용할 수 없을 것입니다.

4 천만 개의 행 테이블이 있고 Python 스크립트는 3-4 시간 내에이를 업데이트합니다.

이제 MySql JSON이 있으므로 더 이상 Python이나 PHP가 필요하지 않습니다. 다음과 같이 할 수 있습니다.

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

간단하고 훌륭해 보입니다. 그러나 속도는 Python 버전보다 10 ~ 20 배 느리고 단일 트랜잭션이므로 다른 응용 프로그램에서는 테이블 데이터를 병렬로 수정할 수 없습니다.

따라서 4 천만 행 테이블에 JSON 키만 복제하려면 30-40 시간 동안 테이블을 전혀 사용하지 않아야합니다. 의미가 없습니다.

를 통해 JSON 필드 내 경험에 직접 액세스로부터 데이터를 읽는 소개 JSON_EXTRACTWHERE훨씬 느린 그 (또한 extremelly 느 TEXTLIKE 없는 인덱스 컬럼에). 가상 생성 열은 훨씬 더 빠르게 수행되지만 데이터 구조를 미리 알고 있으면 JSON이 필요하지 않으며 대신 기존 열을 사용할 수 있습니다. 정말 유용한 JSON을 사용할 때, 즉 데이터 구조를 알 수 없거나 자주 변경되는 경우 (예 : 사용자 지정 플러그인 설정) 가능한 새 열에 대해 정기적으로 가상 열을 생성하는 것은 좋은 생각처럼 보이지 않습니다.

Python과 PHP는 JSON 유효성 검사를 매력처럼 만들므로 MySql 측에서 JSON 유효성 검사가 전혀 필요하지 않은지 의문입니다. XML, Microsoft Office 문서의 유효성을 검사하거나 맞춤법도 검사하지 않는 이유는 무엇입니까? 😉


답변