MySQL : 여러 테이블 또는 여러 열이있는 하나의 테이블?


124

그래서 이것은 디자인 문제에 가깝습니다.

하나의 기본 키 (예 : 사용자 ID)가 있고 해당 사용자와 관련된 많은 정보가 있습니다.

정보에 따라 여러 테이블을 범주로 분류해야합니까? 아니면 여러 열이있는 하나의 테이블 만 가져야합니까?

내가 사용했던 방식은 여러 테이블을 갖는 것이 었습니다. 예를 들어 애플리케이션 사용 데이터 용 테이블 하나, 프로필 정보 용 테이블 하나, 백엔드 토큰 용 테이블 하나 등을 정리하여 정리했습니다.

최근에 어떤 사람은 그렇게하지 않는 것이 낫다고 말했고 많은 열이있는 테이블을 갖는 것이 좋습니다. 문제는 모든 열에 동일한 기본 키가 있다는 것입니다.

저는 데이터베이스 디자인에 익숙하지 않으므로 어떤 접근 방식이 더 좋으며 장단점은 무엇입니까?

기존 방식은 무엇입니까?


명확하게하기 위해, 내가 틀렸다면 정정 해줘,하지만 난 "여러 테이블이"링크 / 연관 테이블로 이해 될 수 있다고 생각 : en.wikipedia.org/wiki/Associative_entity
cellepo

1
이 데이터베이스가 분석 목적 또는 운영 / 트랜잭션 처리에 필요합니까?
Alexander Radev

답변:


112

정보는 일대일 (각 사용자가 하나의 이름과 암호를 가짐)이면 데이터베이스가 결과를 검색하기 위해 수행해야하는 조인 수를 줄이므로 하나의 테이블을 사용하는 것이 좋습니다. 일부 데이터베이스에는 테이블 당 열 수에 제한이 있다고 생각하지만 일반적인 경우에는 걱정하지 않으며 필요하면 나중에 언제든지 분할 할 수 있습니다.

데이터가 일대 다인 경우 (각 사용자가 수천 행의 사용 정보를 가지고 있음) 중복 데이터를 줄이기 위해 별도의 테이블로 분할해야합니다 (중복 데이터는 저장 공간, 캐시 공간을 낭비하고 데이터베이스를 유지하기 어렵게 만듭니다. ).

데이터베이스 정규화 에 대한 Wikipedia 기사가 흥미로운 이유를 찾을 수 있습니다. 그 이유를 자세히 설명하기 때문입니다.

데이터베이스 정규화는 중복성과 종속성을 최소화하기 위해 관계형 데이터베이스의 필드와 테이블을 구성하는 프로세스입니다. 정규화에는 일반적으로 큰 테이블을 더 작은 (그리고 덜 중복 된) 테이블로 나누고 이들 간의 관계를 정의하는 작업이 포함됩니다. 목표는 데이터를 분리하여 필드의 추가, 삭제 및 수정을 하나의 테이블에서만 수행 한 다음 정의 된 관계를 통해 나머지 데이터베이스에 전파 할 수 있도록하는 것입니다.

비정규 화 는 데이터를 읽을 때 데이터베이스가 수행해야하는 작업의 양을 줄이기 때문에 반복되는 데이터가 더 나은 경우가 있기 때문에주의해야 할 사항입니다. 데이터를 가능한 한 표준화하여 시작하고 특정 쿼리의 성능 문제를 알고있는 경우에만 비정규 화하는 것이 좋습니다.


답변 해주셔서 감사합니다. 그래서 제가 말씀 드린 내용은 사용자가 일대일 열을 많이 가지고있는 일대일 정보 상황이라고 생각합니다.
Xavier_Ex

@Xavier_Ex-예, 사용자 당 열이 하나만있는 경우 거대한 사용자 테이블 하나만 작업하기가 더 쉬울 것입니다 (DB 엔진이 최적화하는 것이 훨씬 더 쉽습니다).
Brendan Long

편집 된 게시물은 더 유용한 정보를 제공합니다! 일부 열이 자주 업데이트되는 경우 별도의 테이블에 넣어야한다는 새로운 우려가 있습니다. 예를 들어 사용자의 생년월일은 업데이트되지 않지만 백엔드 토큰은 일정 시간이 지나면 무효화 될 수 있으며 자주 업데이트해야합니다. 성능을 향상시키기 위해 이러한 방식으로 테이블을 분리하면 더 좋을까요? 이제 당신이 언급 한 위키에 대해 읽어
볼게요

@Xavier_Ex-추천하지 않습니다. 하나의 테이블에서 필요한 모든 데이터를 조회 할 수있을 때 훨씬 더 나은 성능을 얻을 수 있습니다 (비정규 화 문서 참조). 조인은 (1) 회전하는 디스크에서 검색을 포함 할 수있는 여러 위치에서 데이터를 검색해야하고, (2) 일반적으로 여러 인덱스와 일종의 병합이 필요하고, (3) 쿼리 계획을 더 어렵게 만듭니다. 시간이 걸리지 만 쿼리 옵티마이 저가 뭔가 잘못 될 가능성이 높아집니다 (그리고 잘못 최적화 된 쿼리는 정말 느릴 수 있습니다 ).
Brendan Long

1
최근에 MySQL InnoDB 테이블의 길이 제한 (~ 8000 바이트)이 상대적으로 작기 때문에 이와 동일한 문제에 직면했습니다. 내 문제 테이블 (매우 긴 보험 양식의 데이터, 100 개 이상의 열)에는 모두 UTF8 인 여러 varchar 열이 있습니다. 그래서 우리는 쉽게 ~ 8000 바이트 제한을 채웠고 항상 "스토리지 엔진에서 오류 139"가 발생했습니다. 그래서 우리는 테이블을 분할해야했습니다. (우리는 최신 Barracuda 형식으로 테스트했으며 분할없이 작동했지만 클라이언트의 서버는 여전히 MySQL 5.0을 사용합니다.)
MV.

12

하나의 큰 테이블은 종종 잘못된 선택입니다. 관련 테이블은 함께 작동하도록 설계된 관계형 데이터베이스입니다. 제대로 인덱싱하고 성능이 좋은 쿼리를 작성하는 방법을 안다면 제대로 수행 될 것입니다.

테이블이 너무 많은 열을 가져 오면 데이터베이스가 정보를 저장하는 페이지의 실제 크기에 문제가 발생할 수 있습니다. 레코드가 페이지에 비해 너무 커져서 사용자를 불편하게 만드는 특정 레코드를 만들거나 업데이트하지 못하거나 (적어도 SQL Server에서) 특정 오버플로가 허용 될 수 있습니다. 데이터 유형 (이 작업을 수행하는 경우 조회해야하는 일련의 규칙 포함)이 있지만 많은 레코드가 페이지 크기를 초과하면 엄청난 성능 문제를 일으킬 수 있습니다. 이제 MYSQL이 페이지를 처리하는 방법과 잠재적 인 페이지 크기가 너무 커질 때 문제가 있는지 여부는 해당 데이터베이스에 대한 문서에서 찾아봐야 할 것입니다.


1
아 다른 목소리! 항상 훌륭합니다. 정보 감사합니다! 나는 테이블을 만들 때 그 점을인지하도록하겠다.하지만 원래 그런 낮은 수준의 물건을 알아야 할 줄은 몰랐다.
Xavier_Ex

4

좋은 예가 있습니다. 다음과 같은 관계 집합이있는 지나치게 정규화 된 데이터베이스 :

people -> rel_p2staff -> staff

people -> rel_p2prosp -> prospects

사람들이 이름과 개인 정보를 가지고있는 경우 직원은 직원 기록 세부 정보 만 있고 잠재 고객은 잠재 고객 세부 정보 만 있으며 rel 테이블은 직원 및 잠재 고객에 연결된 사람들의 외래 키가있는 관계 테이블입니다.

이러한 종류의 디자인은 전체 데이터베이스에 적용됩니다.

이제이 관계 집합을 쿼리하기 위해 매번 다중 테이블 조인이며 때로는 8 개 이상의 테이블 조인입니다. 올해 중반까지 4 만 명의 기록을 넘긴 지금은 매우 느려지기 시작했습니다.

인덱싱 및 모든 낮은 매달려 과일은 작년에 사용되었으며 모든 쿼리는 완벽하게 최적화되었습니다. 이것은 특정 정규화 된 설계 및 관리를위한 도로의 끝이며, 6 개월 동안 데이터베이스의 재구성은 물론 이에 의존하는 전체 애플리케이션의 재 구축을 승인했습니다. $$$$ 아야.

해결책은 다음 people -> staff과 직접적인 관계를 맺는 것입니다.people -> prospect


재건이 어떻게 진행되었는지 알고 싶습니까? 당신은 typea staff또는 a 가 있었던 곳에서 단일 테이블 상속과 유사한 것을 디자인하게 되었습니까 prospect?
Coderama

1
직접 관계된 사람들-> 직원 및 사람들-> 잠재 고객과 함께 갔고, 매력적이고 사용하기 쉽고 쿼리가 빠릅니다.
Vlad

4

이것을 발견하고 MySQL을 많이 사용하고 최근에 Postgres로 전환 한 사람으로서 가장 큰 장점 중 하나는 Postgres의 필드에 JSON 객체를 추가 할 수 있다는 것입니다.

따라서 이러한 상황에있는 경우에는 많은 열이있는 하나의 큰 테이블과 분할 중 하나를 반드시 결정할 필요는 없지만 열을 JSON 개체로 병합하여 줄일 수 있습니다. 예를 들어 주소가 5 개 열이 아니라 하나가 되십시오. 해당 개체에 대해서도 쿼리 할 수 ​​있습니다.


쿼리 중에 json 객체를 사용할 때 성능은 어떻습니까?
dagalti 19

1
@dagalti 성능은 내가 사용한 응용 프로그램에 적합합니다. 나는 내 자신의 벤치마킹을하지 않은, 그러나 이것은 당신에게 유용 할 수 있습니다 arangodb.com/2018/02/...
moinhaque

3

모든 것을 하나의 테이블에 넣으면 해당 사용자에 대해 여러 행이 있습니까? 사용자를 업데이트해야하는 경우 감사 추적을 유지 하시겠습니까? 사용자가 데이터 요소의 인스턴스를 두 개 이상 가질 수 있습니까? (예를 들어 전화 번호와 같은) 나중에 요소 또는 요소 집합을 추가하려는 경우가 있습니까? 예라고 대답하면 외래 키 관계가있는 자식 테이블이있을 가능성이 큽니다.

부모 / 자식 테이블의 장점은 데이터 무결성, 인덱스를 통한 성능 (예 : 플랫 테이블에서도 가능) 및 나중에 필드를 추가해야하는 경우, 특히 필수 필드 인 경우 IMO 유지 관리가 더 쉽습니다.

단점 디자인이 더 어렵고 쿼리가 약간 더 복잡 해짐

그러나 하나의 큰 평면 테이블이 적절한 경우가 많으므로 상황을 확인하여 결정해야합니다.


나를 상기시켜 주셔서 감사합니다! 그래서 제 경우에는 모든 사용자가 하나 이상의 행을 가질 수 없으므로 모든 정보 필드가 일대일 인 경우 만 고려했습니다. 또한 사용자는 한 요소의 개념이 여러 장소에 존재할 수 없다고 생각하므로 동일한 요소의 인스턴스를 두 개 이상 가질 수 없습니다. 세 번째 질문에 대해 예, 테이블에 더 많은 요소를 추가 할 수 있지만 위에서 언급 한 요구 사항을 위반하지는 않습니다. 여러 행을 한 사용자에게 연결하고 싶을 때 부모 / 자식 테이블이 좋다고 생각하지만이 경우 사용자가 많은 일대일 열을 가지고 있다는 점이 우려됩니다.
Xavier_Ex

모든 요소가 현재 일대일 인 경우에도 부모 / 자식 테이블 IMO를 가질 필요 나 욕구를 제거하지 않습니다. 변경된 데이터의 로그를 유지하는 것은 한 가지 용도입니다. 지연 로딩 객체는 또 다른 것입니다. 단일 테이블 구조에 이점이있는 동안 부모 자식 레이아웃에도 이점이 있습니다 (사람들이 이것으로 극단으로 이동하는 것을 보았지만).
Brian

1

나는 이미 일종의 데이터베이스 설계를 완료했습니다. 저에게는 데이터베이스 관리 시스템의 어려움에 달려 있습니다. 네, 한곳에 만 고유 한 데이터가있는 것은 사실이지만 많은 레코드가있는 지나치게 정규화 된 데이터베이스로 쿼리를 만드는 것은 정말 어렵습니다. 두 스키마를 결합하기 만하면됩니다. 페이스 북, 지메일 등과 같이 관리하기 어려운 방대한 기록이있을 것이라고 생각되면 하나의 거대한 테이블을 사용하십시오. 그리고 간단한 시스템을 위해 한 세트의 레코드에 다른 테이블을 사용하십시오 ... 글쎄 이것은 제 의견입니다 .. 도움이 되었으면 좋겠습니다.


1
"대량의 레코드가있을 경우 하나의 거대한 테이블을 사용하십시오."그러나 Facebook, Google은 사용자 데이터를 단일 테이블에 저장하지 않고 여러 테이블로 분리했습니다.
Yami Odymel

0

이를 수행하는 일반적인 방법은 스타 스키마 또는 눈송이 스키마에서와 같이 다른 테이블을 사용하는 것입니다. Howeevr, 저는이 전략을 두 배로 만들 것입니다. 저는 데이터가 한곳에 만 존재해야한다는 이론을 믿습니다. 제가 언급 한 스키마에 대해서는 잘 작동 할 것입니다. 그러나보고 엔진과 BI 제품군의 경우보고 요구 사항을보다 지원하기 때문에 열 방식의 접근 방식이 매우 유용 할 것이라고 생각합니다. infobright.org와 같은 컬럼 방식 접근 방식은 성능이 크게 향상되고 압축되어 두 접근 방식을 매우 유용하게 사용할 수 있습니다. 많은 기업들이 조직에 단 하나의 데이터베이스 아키텍처 만있는 것이 전체 요구 사항을 지원하지 않는다는 사실을 깨닫기 시작했습니다. 많은 회사가 둘 이상의 데이터베이스 구조를 갖는 개념을 모두 구현하고 있습니다.


덕분에 정보를하지만, 미안 해요 확실히 대답을 이해하지 ... 내가 ... 먼저 언급 한 두 스키마에 대한 검색을 할 수 있습니다
Xavier_Ex

-4

단일 테이블을 갖는 것이 더 효과적이라고 생각하지만 테이블이 동일한 행의 변수의 차이뿐만 아니라 관계, 추세를 보여주는 방식으로 구성되어 있는지 확인해야합니다. 예를 들어, 표에 학생의 연령과 성적이 표시되어있는 경우 가장 높은 점수를받은 사람이 가장 낮은 점수를받은 사람과 잘 구별되고 학생의 연령 차이가 균등하도록 테이블을 정렬해야합니다.

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