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


113

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 데이터 유형의 장단점.


오 제발 당신이하는 말은하지 마세요. 여기, 이것을 읽으십시오 . 당신의 것은 나쁜 생각에 대한 또 다른 변형입니다.
Drew

@Drew 큰 대답을하셨습니다. 하지만 내 질문이 아닙니다. json 데이터에 대한 쿼리를 작성하면 SQL 규칙을 건너 뛸 수 있다는 것을 알고 싶습니다. 우리는 많은 테이블이 필요하지 않기 때문에
Imran

1
당신은 말했다 Now it is possible to store more complex data in column. 조심하십시오
Drew

2
Json 데이터 유형 지원 인덱스 및 스마트 크기 : 64K 및 4G. 그래서 2000 데이터를 저장하고 관계가있는 5 테이블 대신 5 중첩 레이블을 추가하려면 어떻게해야합니까?
Imran

5
"이 기능에 대해 더 알고 싶습니다." 및 "MySQL JSON 데이터 유형의 장단점." 질문이 아니며 질문이 너무 광범위하다고 바꿔 표현하면 "그래서 MySQL에서 복잡한 스키마 구조와 외래 키를 생각한 적이 없습니다. 몇 개의 테이블 만 사용하여 복잡한 관계를 저장합니다." JSON은 관계 및 FK가 아니기 때문에 자기 모순입니다. "is this good"에 대한 설명은 관계형 모델에 대한 소개 일 뿐이므로 너무 광범위합니다. 몇 가지 예를 살펴보고 참조를 통해 장단점 목록을 만들고 어디에서 잘못되었는지 물어보십시오.
philipxy

답변:


57
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 함수가 아닌 다른 유형의 표현식에서 작동합니다.


7
슬라이드 링크를
Paul Campbell

좋은 점은 두 기술이 모두 우수하다는 것은 우리의 요구에 맞는 기술과 보안 및 성능 측면에서 더 많은 이점을 제공하는 것을 결정한다는 것을 의미합니다.
Christopher Pelayo

1
문제의 핵심은 JSON의 모든 새 키에 대해 생성 된 열의 색인을 사용하려면 ALTER TABLE이 여전히 필요하다는 것입니다. 지적되어 기쁩니다.
user1454926

가상 열 및 / 또는 인덱스를 추가해야하는 경우에만. JSON 데이터를 "블랙 박스"로 취급하고 JSON 내의 하위 필드를 검색하거나 정렬하는 쿼리를 수행하지 않으면 그렇게 할 필요가 없습니다. 그렇기 때문에 JOIN, WHERE또는 다른 절 에서 JSON을 참조하지 않는 것이 좋습니다 . 선택 목록에서 JSON 열을 가져 오면됩니다.
Bill Karwin

슬라이드 링크가 끊어졌습니다. @BillKarwin.
lakesare

43

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

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

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

...

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

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

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

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

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


7
하나의 단점; JSON 데이터 유형은 데이터 유형, TEXT 및 BLOB와 같은 Mysql 메모리 테이블에서 지원되지 않습니다. 즉, 임시 테이블이 필요한 경우 메모리가 아닌 디스크 기반 테이블을 생성합니다. : 일부 임시 테이블이 여기에 설명 된 사용되는 경우 dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html
raiz 미디어

1
@raizmedia 디스크 기반 테이블이 메모리와 비교하여 문제가되는 이유를 설명해 주시겠습니까?
라팽

@lapin 아마도 속도 제한 때문일 것입니다.
Little Helper

@LittleHelper는 PCI 4x 40Gb / s M.2 슬롯을 사용하고 40Gb / s 지원 드라이브를 삽입하면 피할 수 있습니다. 이것은 메모리만큼 빠르게 작동합니다. 메모리를 포맷하는 데 사용되는 해당 드라이브에 특수 포맷을 적용 할 수도 있습니다.
세르게이 로마노프

@SergeyRomanov, [citation required]드라이브 대 RAM을 벤치마킹 했습니까?
Bill Karwin

11

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

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. 게으르지 마십시오

감사


2
VIRTUAL 열 사용에 관심이있을 수 있습니다. percona.com/blog/2016/03/07/…
Bell

10

내 경험상, 적어도 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 문서의 유효성을 검사하거나 맞춤법도 검사하지 않는 이유는 무엇입니까? ;)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.