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

내 테이블에 사용자 관련 데이터를 저장하기 위해 다음 모델을 구현하고 있습니다 .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?



답변

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이 쿼리 할 필요가없고 표시 용으로 만 사용되는 정보를 설명하는 경우 모든 데이터 포인트에 대해 별도의 열을 작성하는 것이 과도 할 수 있습니다.


답변

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

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

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

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

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

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

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

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

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


답변

그냥 그것을 던지지 만 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


답변

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

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

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

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

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


답변

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

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

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

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


답변

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

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

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

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

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

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

편집하다:

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

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

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


답변

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