데이터베이스에 JSON 저장 및 각 키에 대한 새 열 보유


213

내 테이블에 사용자 관련 데이터를 저장하기 위해 다음 모델을 구현하고 있습니다 .2 열 uid(기본 키)과 meta사용자에 대한 다른 데이터를 JSON 형식으로 저장 하는 열이 있습니다.

 uid   | meta
--------------------------------------------------
 1     | {name:['foo'], 
       |  emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
 2     | {name:['sann'], 
       |  emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------

테이블이 uid,, name등의 많은 열을 갖는 속성 당 하나의 열 모델보다이 방법이 더 좋습니다 (성능, 디자인) emailid.

첫 번째 모델에서 내가 좋아하는 것은 가능한 한 많은 필드를 추가 할 수 있다는 것입니다.

또한 첫 번째 모델을 구현 했으므로 궁금합니다. 'foo'와 같은 이름을 가진 모든 사용자를 가져오고 싶은 것처럼 어떻게 쿼리를 수행합니까?

질문 -JSON 또는 필드 당 열을 사용하여 데이터베이스에 사용자 관련 데이터를 저장하는 더 좋은 방법은 무엇입니까 (필드 수는 고정되어 있지 않음을 명심하십시오)? 또한 첫 번째 모델이 구현 된 경우 위에서 설명한대로 데이터베이스를 쿼리하는 방법은 무엇입니까? 쿼리에서 검색 할 수있는 모든 데이터를 별도의 행에 저장하고 다른 데이터를 JSON의 다른 행에 저장하여 두 모델을 모두 사용해야합니까?


최신 정보

검색을 수행해야하는 열이 너무 많지 않으므로 두 모델을 모두 사용하는 것이 현명합니까? 검색 해야하는 데이터의 열당 키 및 다른 사람 (같은 MySQL 데이터베이스의 경우)의 JSON?


40
좋은 질문입니다! 그런데 왜 대답을받지 않았습니까? 그것은 다른 사용자들 (나 같은)을 도울 것입니다
Sahar Ch.

답변:


198

2017 년 6 월 4 일 업데이트

이 질문 / 답변이 인기를 얻었으므로 업데이트 할 가치가 있다고 생각했습니다.

이 질문이 처음 게시되었을 때 MySQL은 JSON 데이터 형식을 지원하지 않았으며 PostgreSQL의 지원은 초기 단계였습니다. 5.7부터 MySQL은 이제 JSON 데이터 형식 (이진 저장소 형식)을 지원하며 PostgreSQL JSONB 는 크게 발전했습니다. 두 제품 모두 JSON 객체의 특정 키 인덱싱 지원을 포함하여 임의의 문서를 저장할 수있는 고성능 JSON 유형을 제공합니다.

그러나 나는 관계형 데이터베이스를 사용할 때 기본 환경 설정이 여전히 값 당 열이어야한다는 원래의 진술을 그대로 유지합니다. 관계형 데이터베이스는 여전히 그 안의 데이터가 상당히 잘 정규화 될 것이라는 가정하에 구축됩니다. 쿼리 플래너는 JSON 문서에서 키를 볼 때보 다 열을 볼 때 더 나은 최적화 정보를 갖습니다. 외래 키는 열 사이에 만들 수 있지만 JSON 문서의 키 사이에는 생성되지 않습니다. 중요하게도, 대부분의 스키마가 JSON을 사용하여 정당화하기에 충분히 휘발성 인 경우 관계형 데이터베이스가 올바른 선택인지 적어도 고려해야합니다.

즉, 완벽하게 관계형이거나 문서 지향적 인 응용 프로그램은 거의 없습니다. 대부분의 응용 프로그램에는 두 가지가 혼합되어 있습니다. 다음은 개인적으로 관계형 데이터베이스에서 JSON이 유용한 것으로 밝혀진 몇 가지 예입니다.

  • 연락처의 이메일 주소와 전화 번호를 JSON 배열에 값으로 저장하는 것이 여러 개의 개별 테이블보다 관리하기 훨씬 쉬운 경우

  • 임의의 키 / 값 사용자 환경 설정 저장 (값은 부울, 텍스트 또는 숫자 일 수 있으며 다른 데이터 유형에 대해 별도의 열을 원하지 않음)

  • 정의 된 스키마가없는 구성 데이터 저장 (Zapier 또는 IFTTT를 빌드 중이고 각 통합에 대한 구성 데이터를 저장해야하는 경우)

나는 다른 것들도 있다고 확신하지만 이것들은 몇 가지 간단한 예입니다.

원래 답변

임의의 문서 크기 제한 이외의 제한없이 원하는만큼 많은 필드를 추가하려면 MongoDB와 같은 NoSQL 솔루션을 고려하십시오.

관계형 데이터베이스의 경우 : 값당 하나의 열을 사용하십시오. JSON Blob을 열에 넣으면 쿼리가 사실상 불가능 해집니다 (실제로 작동하는 쿼리를 찾을 때 고통스럽게 느려집니다).

관계형 데이터베이스는 인덱싱 할 때 데이터 형식을 활용하며 정규화 된 구조 로 구현됩니다 .

참고로 이것은 관계형 데이터베이스에 JSON을 저장해서는 안된다는 말은 아닙니다. 실제 메타 데이터를 추가하거나 JSON이 쿼리 할 필요가없고 표시 용으로 만 사용되는 정보를 설명하는 경우 모든 데이터 포인트에 대해 별도의 열을 작성하는 것이 과도 할 수 있습니다.


1
검색을 수행해야하는 열이 너무 많지 않으므로 두 모델을 모두 사용하는 것이 현명합니까? 검색 해야하는 데이터의 열당 키 및 다른 사람 (같은 MySQL 데이터베이스의 경우)의 JSON?
ShuklaSannidhya

3
@Sann 자주 읽 거나 쿼리 하려는 데이터에 대해 값당 열을 사용해야합니다 . 누군가의 이름을 JSON에 넣는 것은 의미가 없습니다. 왜냐하면 그것을 기반으로 쿼리 할 가능성은 없지만 매우 자주 필요하기 때문 입니다. 그것은 응용 프로그램 측에서 많은 낭비되는 디코딩입니다. 당신이하지 않으면 정말 데이터가 더 나은 JSON으로 표시됩니다 같은 느낌 (저와 신뢰, 아마 아니다), 당신은에 의존해서는 안된다.
Colin M

5
" virtually impossible to query"-오늘 psql을 사용하면 jsonb를 검색하고 색인을 생성 할 수 있습니다
ted

1
@ted true입니다. 그러나이 답변을 작성할 당시에는 실제로 사용할 수 없었습니다. 또한이 질문은 기능이없는 MySQL을 언급합니다.
Colin M

3
@ColinM, 그렇습니다, 나는 나의 코멘트가 당신의 포스트보다 3 년 더 젊다는 것을 알고 있습니다. 내가 떠난 이유는 다른 사람들에게 도움이되고 결정이 바뀌기 때문입니다. MySQL에 대한 언급에 관해서는 : 사실 일 수는 있지만 "For relational databases"대답은 = P
ted

69

대부분의 것들과 마찬가지로 "의존한다". 열이나 JSON에 데이터를 저장하는 것은 옳고 그름 / 좋거나 나쁘지 않습니다. 나중에 수행해야 할 작업에 따라 다릅니다. 이 데이터에 액세스하는 예상 방법은 무엇입니까? 다른 데이터를 상호 참조해야합니까?

다른 사람들은 기술적 인 트레이드 오프가 무엇인지 꽤 잘 대답했습니다.

시간이 지남에 따라 앱과 기능이 발전하고이 데이터 스토리지 결정이 팀에 미치는 영향에 대해 논의한 사람은 많지 않습니다.

JSON을 사용하려는 유혹 중 하나는 스키마 마이그레이션을 피하는 것이기 때문에 팀이 훈련되지 않으면 다른 키 / 값 쌍을 JSON 필드에 고정하는 것이 매우 쉽습니다. 마이그레이션은 없으며 아무도 그 목적을 기억하지 못합니다. 그것에 대한 유효성 검사가 없습니다.

우리 팀은 postgres의 전통적인 열과 함께 JSON을 사용했으며 처음에는 얇게 썬 빵 이후 가장 좋았습니다. JSON은 매력적이면서도 강력했습니다. 언젠가는 유연성이 대가를 치르고 갑자기 심각한 문제가된다는 것을 깨달았습니다. 때로는 그 점이 정말 빨리 올라가고이 디자인 결정 위에 다른 많은 것들을 구축했기 때문에 변경하기가 어려워집니다.

시간이 지남에 따라 새로운 기능을 추가하고 JSON으로 데이터를 가져 오면 기존 열을 고수했을 때 추가 된 것보다 복잡한 쿼리가 발생했습니다. 그런 다음 특정 키 값을 다시 열로 가져와 결합하여 값을 비교할 수있었습니다. 나쁜 생각. 이제 중복되었습니다. 새로운 개발자가 와서 혼란 스러울까요? 다시 저장해야하는 가치는 무엇입니까? JSON 또는 열입니까?

JSON 필드는 이것과 작은 조각의 정크 서랍이되었습니다. 데이터베이스 수준에서 데이터 유효성 검사, 문서 간 일관성 또는 무결성이 없습니다. 따라서 기존 열에서 엄격한 유형 및 제약 조건 검사를받는 대신 모든 책임을 앱에 적용했습니다.

되돌아 보면 JSON을 통해 매우 빠르게 반복하고 무언가를 얻을 수있었습니다. 그것은 훌륭했다. 그러나 특정 팀 규모에 도달 한 후에는 유연성이 뛰어 나기 때문에 기술 부채가 길어 향후 기능 진화 진행 속도가 느려졌습니다. 주의해서 사용하십시오.

데이터의 본질이 무엇인지에 대해 길고 열심히 생각하십시오. 앱의 기초입니다. 시간이 지남에 따라 데이터가 어떻게 사용됩니까? 그리고 어떻게 변경 될 가능성이 있습니까?


7
"유연성 덕분에 기술 부채가 길어질 수있었습니다."
Antoine Gallix

수년간의 개발과 다른 사람들과 함께 일한 후,이 주제에 대해 글을 써야한다면 같은 것을 쓸 것입니다. 현재는 많은 개발자가 있으며, 수년간의 경험에도 불구하고 실제로는 레벨 업하지 않는 개발자가 많습니다. 우리는 모든 것을 단순하게 유지해야하며, 성공을 "프레임 워크"할 수 있다고 항상 고려해야하는 2 가지 사항은 코드의 확장 성 및 유지 관리 성입니다.
JohnnyJaxs

27

그냥 그것을 던지지 만 WordPress에는 이런 종류의 물건에 대한 구조가 있습니다 (적어도 WordPress는 내가 그것을 관찰 한 첫 번째 장소였으며 아마도 다른 곳에서 시작되었을 것입니다).

무제한 키를 허용하며 JSON Blob을 사용하는 것보다 검색 속도가 빠르지 만 NoSQL 솔루션만큼 빠르지는 않습니다.

uid   |   meta_key    |   meta_val
----------------------------------
1         name            Frank
1         age             12
2         name            Jeremiah
3         fav_food        pizza
.................

편집하다

히스토리 / 복수 키 저장

uid   | meta_id    |   meta_key    |   meta_val
----------------------------------------------------
1        1             name            Frank
1        2             name            John
1        3             age             12
2        4             name            Jeremiah
3        5             fav_food        pizza
.................

다음과 같은 것을 통해 쿼리하십시오.

select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc

1
NoSQL 솔루션이 제대로 인덱스 키에서 관계형 쿼리보다 실제로 성능이 더 좋은지 궁금합니다. 나는 이것과 같은 1 레벨 예제에서 다소 동일해야한다고 생각합니다.
Bruno

+1. 나도 알아 차렸다! 그러나 그것은 당신에게 거대한 테이블을 제공합니다 (행으로). 또한 사용자가 이름을 변경하면 여러 값을 저장할 수 없지만 이전 이름도 유지하려면 JSON 유형 데이터 모델이 필요합니다.
ShuklaSannidhya

@Sann, JSON에서 이전 값을 유지하려면 키의 이름을 바꿔야합니다. EAV (이 예제) 또는 JSON으로 할 수 있습니다. 특별히 다르지 않습니다.
Bruno

그것은 큰 테이블을 제공하지만 중복 값의 경우 JSON과 동일한 문제가 발생합니다. 동일한 수준에서 중복 키를 가질 수 없으며 (예 : 두 개의 "이름"키) 예측 가능한 동작을 기대할 수 있습니다.
Adam

물론 중복 키를 가질 수는 없지만 해당 키와 연관된 배열을 가질 수 있습니다. emailid내 질문에 주어진 예 에서 키를 확인하십시오 .
ShuklaSannidhya

13

접근 방식의 단점은 정확히 당신이 언급 한 것입니다.

텍스트 검색을 수행해야 할 때마다 물건을 찾는 것이 매우 느려집니다.

대신 열당 값은 전체 문자열과 일치합니다.

접근 방식 (JSON 기반 데이터)은 검색 할 필요가없고 일반 데이터와 함께 표시해야하는 데이터에 적합합니다.

편집 : 명확히하기 위해 위의 고전적인 관계형 데이터베이스가 사용됩니다. NoSQL은 내부적으로 JSON을 사용하며 원하는 동작이라면 더 나은 옵션 일 것입니다.


1
그러니까 둘 다 사용해야 해요 검색 해야하는 데이터의 열당 키 및 다른 사용자의 경우 JSON입니다.
ShuklaSannidhya

4
예. 이렇게하면 열당 데이터 필드를 검색하여 필요한 성능을 얻고 필요한 경우 코드에서 사용할 JSON blob을 가져옵니다.
Nick Andriopoulos

9

기본적으로 사용중인 첫 번째 모델을 문서 기반 스토리지라고합니다. MongoDB 및 CouchDB와 같은 널리 사용되는 NoSQL 문서 기반 데이터베이스를 살펴 봐야 합니다. 기본적으로 문서 기반 DB에서는 데이터를 json 파일에 저장 한 다음 이러한 json 파일을 쿼리 할 수 ​​있습니다.

두 번째 모델은 널리 사용되는 관계형 데이터베이스 구조입니다.

MySql과 같은 관계형 데이터베이스를 사용하려면 두 번째 모델 만 사용하는 것이 좋습니다. MySql을 사용하고 첫 번째 모델 에서처럼 데이터를 저장하는 데는 아무런 의미가 없습니다 .

두 번째 질문에 답하기 위해 first model을 사용하는 경우 'foo'와 같은 이름을 쿼리하는 방법이 없습니다 .


두 모델을 모두 사용하는 것이 현명합니까? 검색 해야하는 데이터의 열당 키 및 다른 데이터베이스 (동일한 데이터베이스의 경우)의 JSON?
ShuklaSannidhya

@ 산-하하. 그것은 데이터 복제입니다. 두 데이터 조각이 항상 동일한 지 확인해야합니다. 데이터 중 하나가 특정 시점에 있어도 데이터가 깨끗하지 않아 심각한 문제가 발생할 수 있습니다. 그래서 제 대답은 NO입니다
Girish

그러나 중복 데이터가 작을 때 중복은 비용이 많이 들지 않습니다. 예를 들어, 검색을 수행해야하는 필드가 두 개뿐이므로 두 개의 새 열을 생성하고 [아마도] JSON 데이터에서 제거합니다. . 비용이 많이 들지 않습니까?
ShuklaSannidhya

성능을보고있는 경우 MongoDB 및 CouchDB는 MySql보다 빠른 읽기 및 쓰기 작업을 제공합니다. 대부분의 사용 사례에 필요하지 않은 관계형 데이터베이스에는 많은 기능을 제공하지 않기 때문입니다.
Girish

API에서 JSON 객체 / 콜백을 저장하면 이점이 없습니까? 예를 들어 URL, Thumb 등을 위해 YouTube의 API를 호출하는 대신 JSON 객체에 대한 로컬 DB (mysql, lite 등)를 쿼리 할 수 ​​있습니까? 잘 모르겠습니다. 특히 캐시하거나 앱을 더 빨리 실행하려고하는 경우 나에게 의미가 있습니다. 그러나 나는 전문가가 아닙니다 : /
markbratanov

4

관계형 모델을 사용할지 여부를 주로 망설이는 것 같습니다.

알다시피, 귀하의 예는 관계형 모델에 합리적으로 적합하지만이 모델을 진화시켜야 할 때 문제가 발생할 수 있습니다.

기본 엔터티 (사용자)에 대해 하나의 (또는 미리 결정된) 수준의 속성 만있는 경우 관계형 데이터베이스에서 여전히 EAV (Entity Attribute Value) 모델을 사용할 수 있습니다. (이것에는 장단점이 있습니다.)

응용 프로그램을 사용하여 검색하려는 구조화 된 값이 줄어들 것으로 예상되는 경우 MySQL이 최선의 선택이 아닐 수 있습니다.

PostgreSQL을 사용하고 있다면 두 가지 이점을 모두 누릴 수 있습니다. (이거 진짜 데이터의 실제 구조에 달려 있습니다 ... MySQL은 반드시 잘못된 선택이 아니며 NoSQL 옵션이 관심이 될 수 있습니다. 대안을 제안하고 있습니다.)

실제로 PostgreSQL은 (불변의) 함수 (MySQL이 알 수없는 한) 에 대한 색인을 작성할 수 있으며 최근 버전에서는 JSON 데이터에서 PLV8을 직접 사용 하여 관심있는 특정 JSON 요소에 대한 색인을 작성할 수 있습니다. 해당 데이터를 검색 할 때 쿼리 속도

편집하다:

검색을 수행해야하는 열이 너무 많지 않으므로 두 모델을 모두 사용하는 것이 현명합니까? 검색 해야하는 데이터의 열당 키 및 다른 사람 (같은 MySQL 데이터베이스의 경우)의 JSON?

두 모델을 혼합하는 것이 반드시 틀린 것은 아니지만 (추가 공간이 무시할 수 있다고 가정 할 경우) 두 데이터 세트가 동기화 된 상태로 유지되지 않으면 문제가 발생할 수 있습니다. .

이를 수행하는 좋은 방법은 업데이트 또는 삽입이 수행 될 때마다 데이터베이스 서버 내에서 스토어드 프로 시저를 실행하여 트리거가 자동 업데이트를 수행하도록하는 것입니다. 내가 아는 한, MySQL 저장 프로 시저 언어는 아마도 모든 종류의 JSON 처리를 지원하지 않습니다. PLV8을 지원하는 PostgreSQL (및보다 유연한 저장 프로 시저 언어를 가진 다른 RDBMS)이 더 유용해야합니다 (트리거를 사용하여 관계형 열을 자동으로 업데이트하는 것은 동일한 방식으로 인덱스를 업데이트하는 것과 매우 유사합니다).


위에서 말한 것 외에도 PostgreSQL 9.4 이상에서 JSONB 데이터 유형의 연산자를 살펴볼 가치가 있습니다.
Bruno

1

테이블의 조인 시간이 오버 헤드가됩니다. OLAP에 대해 말할 수 있습니다. 두 개의 테이블이 있으면 하나는 ORDERS 테이블이고 다른 하나는 ORDER_DETAILS입니다. 모든 주문 세부 정보를 얻기 위해 두 테이블을 조인해야하므로 테이블에 증가하는 행이 수백만 정도가 될 때 쿼리 속도가 느려집니다. 왼쪽 / 오른쪽 조인이 내부 조인보다 너무 느립니다. 각 ORDERS 항목에 JSON 문자열 / 객체를 추가하면 JOIN을 피할 수 있다고 생각합니다. 보고서 생성 속도가 빨라집니다 ...


1

짧은 대답 당신은 그들 사이에 혼합해야합니다, 당신은 연락처 데이터, 주소, 제품 variabls와 같은 그들과 관계를 만들지 않을 데이터에 대해 json을 사용하십시오


0

당신은 관계형 데이터베이스에 비 관계형 모델에 맞게하려고, 난 당신이 더 나은 같은되는 NoSQL 데이터베이스를 사용하여 제공 될 것이라고 생각 MongoDB를 . 필드 수에 제한이없는 요구 사항에 맞는 사전 정의 된 스키마는 없습니다 (일반 MongoDB 콜렉션 예제 참조). 문서 를 쿼리하는 방법에 대한 아이디어를 얻으려면 MongoDB 설명서 를 확인하십시오.

db.mycollection.find(
    {
      name: 'sann'
    }
)

2
호기심으로 인해 그의 모델이 비관 계적이라고 가정했습니다. 위의 정보는 나와 매우 관련이있는 것 같습니다.
Colin M

0

다른 사람들이 지적했듯이 쿼리 속도가 느려집니다. 대신 쿼리에 '_ID'열을 추가하는 것이 좋습니다.

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