데이터베이스 디자인-매번 상태를 저장합니까?


17

관계형 데이터베이스 응용 프로그램과 "사용자"개체 및 "메시지"개체가 있다고 가정하겠습니다. 이제이 사용자에게 읽지 않은 메시지 수를 표시하려고합니다.

이것을 보관하는 가장 좋은 방법은 무엇입니까? 사용자에게 필드를 소개하고 사용자가 메시지를 받으면 필드를 세고 읽은 경우 카운트를 줄입니까? 또는 읽지 않은 것으로 플래그가 지정된 사용자의 메시지 수를 계산하기 위해 매번 쿼리를 실행합니까?

첫 번째 방법은 더 복잡하고 오류가 발생하기 쉽지만 두 번째 방법보다 성능이 우수하다고 생각합니다.

이것이 어떻게 정상적으로 이루어 지거나 더 나은 방법은 무엇입니까?


1
여러 요인에 따라 달라집니다 : DB가 분할되어 있습니까? 행 / 사용자 수는 몇 개입니까? 총 DB 크기는 어느 정도입니까 (또는 총 사용자 수)? 초당 몇 개의 요청이 예상됩니까? 이 모든 것이 정확할 필요는 없지만 몇 가지 거친 아이디어가 있습니다.
Omer Iqbal

10
+1 이것은 고전적인 관계형 데이터베이스 질문입니다. 정상화 또는 정상화하지 않습니까? 그게 문제입니다. 스키마에서 귀족이 터무니없는 복제의 슬링과 화살을 겪을 것인지, 아니면 트리거를 취하고, 그것을 채택하여 끝낼 것인가?
로스 패터슨

나는 이것이 언데드인지 고전적인 Rel이라고 주장한다. db. 질문, 사이트에 이미 답변이 있어야합니다.이 답변은 DUP로 마감해야합니다. 그렇지 않으면 답변이 없어야합니다.
mattnz

답변:


14

이것이 어떻게 정상적으로 이루어 지거나 더 나은 접근법은 무엇입니까?

가장 좋은 방법은 추가 필드없이 먼저 시도하고 성능을 측정 한 다음 실제로 속도가 너무 느리면 최적화를 시도하는 것입니다. 이는 추가 필드를 사용하여 첫 번째 방법으로 전환하는 것을 의미 할 수 있지만 메시지의 결합 된 필드 ( "읽지 않은", "userID")에 추가 색인을 추가하는 등 다른 옵션도 테스트해야합니다.


2
가장 좋은 방법은 (더 간단한 방법을 먼저 사용하는 것)입니다. 일반적인 규칙은 구체적인 것보다 낫습니다. (하지만 "test!"의 경우 +1)
DougM

9

데이터베이스 이론에 따른 교과서 솔루션은 데이터베이스 에 다른 데이터의 값에 의존하는 값이 없어야합니다. 이는 전 이적 종속성 이기 때문 입니다. 다른 필드를 기반으로 계산 된 값의 필드를 갖는 것은 중복 정보로 이어지기 때문에 정규화를 위반하는 것입니다.

그러나 때로는 교과서의 내용과 실제로 가장 실용적인 방법이 다릅니다. 각 페이지 뷰에서 읽지 않은 메시지 수를 계산하는 데는 많은 비용이 소요될 수 있습니다. user-table 에서 숫자를 캐싱하면 성능이 훨씬 좋아집니다. 데이터베이스에 불일치가 존재할 수있는 비용이 발생합니다. 읽지 않은 카운터를 업데이트하는 것을 기억하지 않고 메시지를 삭제, 추가 또는 읽을 수 있습니다.


4
INSERT또는 카운터를 조정하는 트리거로 일관성 문제를 쉽게 해결할 수 DELETE있습니다. (또는 UPDATE메시지 소유자 변경을 설명하기 위해). 좋은 DBMS는 작업을 수행하고 동일한 트랜잭션에서 트리거를 실행하므로 모두 또는 전혀 발생하지 않습니다.
Blrfl

4

잠재적 인 문제는 성능이며 아직 성능 문제가 없습니다. 솔루션 # 1에서이를 처리하기 위해 선택한 데이터베이스 (인덱싱, 하드웨어, 캐싱 등)에 따라 수행 할 수있는 많은 작업이 있습니다.이 모든 것은 사용자가 현재 읽지 않은 메시지 수를 얻는 빈도에 따라 다릅니다. 이러한 선택의 대부분은 앱 측에서 사용자 지정 코딩이 필요하지 않으므로 코드 변경 또는 거의 변경없이 구현할 수 있습니다. 앱으로 쉽게 확장 할 수 있습니다.

일단 사용자가 연결 / 로그인하면 데이터베이스에서 카운트를 한 번 얻는 것이 그렇게 나쁘지 않습니다. 앱이 이메일과 같은 메시지 목록을 지속적으로 업데이트합니까? 여기에서 읽지 않은 수를 가져 오는 데 데이터베이스를 다시 방문 할 필요가 없으며 새 메시지를 얻으려면 어쨌든 db 여행을해야합니다.

IsRead?를 플래그 지정하기 위해 메시지를 읽을 때마다 db로 이동합니다. 다른 필드를 다시 계산하지 않으면 필드가 충분합니다.

솔루션 # 2 (필드 / 디스크의 카운트 유지)를 사용하면 문제가있을 때 주기적으로이 필드를 재 구축 / 재 계산하는 루틴이 필요합니까? 그리고 항상 문제가 있습니다. 이 모든 것을 거래에 담을 것입니까? 누군가 다른 사람에게 메시지를 보낼 때마다 User 테이블의 잠금으로 인해 수신 사용자의 UnreadCount를 업데이트 할 수 없어서 실패 할 수 있습니까? 아니면이 필드에 대해 별도의 테이블을 작성 하시겠습니까?


카운트 필드를 최신 상태로 유지하는 것과 관련된 성능 문제를 언급 한 +1
winkbrace

0

내가하는 방법은 매번 쿼리, 즉 두 번째 접근법을 실행하는 것입니다. 쿼리 성능을 향상시키기 위해 users 테이블에 외래 키 역할을하는 열의 메시지 테이블에 인덱스를 추가해야합니다.

그런 다음 Doc이 말한 것처럼이 방법의 성능을 측정하면 다른 경로를 사용해야하는지 여부를 알 수 있습니다.

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