다른 테이블의 데이터를 하나로 모으는 것이 좋지 않습니까?


12

배경

나는 큰 건강 기록 DB (SP, 기능, 작업 등 작성)에 대한 많은 큰 보고서를 작성하고 일반적으로 유지 관리합니다. 원래 스키마와이를 사용하는 소프트웨어는 다른 공급 업체에서 제공 한 것이므로 구조적으로 많은 부분을 변경할 수 없습니다. 실험실, 절차, 백신 등과 같은 추적이 필요한 많은 레코드가 있으며 수십 개의 테이블에 흩어져 있으며, 그 중 많은 부분이 부풀어지고 색인이 잘못되어 있습니다 (일부 문제를 해결할 수있었습니다).

문제

문제는 DB를 거의 제어 할 수없고 특정 업데이트 나 패치에서 변경 될 수 있기 때문에 특히 보고서가 너무 많고 지루한 경우가 많으며 특히 중복되는 부분이 많을 때입니다. 패치 하나만 ​​있으면 12 개 보고서의 상당 부분을 다시 작성해야합니다. 또한 조인, 중첩 선택 및 파일 누적 적용으로 쿼리가 난독 화되고 느려집니다.

내 "솔루션"

내 계획은이 모든 레코드를 하나의 "포괄"테이블에 기록하고 원래 테이블에 트리거를 작성하여이 집계 테이블에 레코드를 유지하는 것입니다. 물론 업데이트 후에도 트리거가 손상되지 않았는지 확인해야하지만 유지 관리 측면에서 보면 데이터를 참조하는 것이 훨씬 쉬울 것입니다.

테이블은 얇고 길며 필요한 데이터 만 저장합니다.

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)

그런 다음 type_id 및 항목 그룹화와 같은 다양한 관계형 테이블이 있습니다.

나는이 테이블 중 일부가 꽤 많이 쓰여짐에 따라이 아이디어를 두 번째 추측하기 시작합니다. 내가 작성할 SP 및 보고서는 데이터를 많이 참조 할 것입니다. 따라서이 테이블이 너무 많은 I / O로 인해 레코드 잠금 및 성능 악몽이 될까 걱정됩니다.

내 질문

나쁘거나 좋은 생각입니까? SQL Server (2008 r2 Standard Edition BTW)와 "때때로"규칙에서 모든 상황이 다르다는 것을 알고 있지만 실제로 일반적인 조언을 찾고 있습니다.

서비스 브로커 사용을 고려하기 시작했지만 간단한 업데이트 / 삽입 만 수행하고 있습니다 ( 허용 된 답변의 대안 참조 ). 대부분의 경우 데이터는 실시간이어야하므로 백업 DB를 사용하면 실제로 작동하지 않습니다. 성능은 이미 다소 문제가되지만 대부분은 곧 해결 될 하드웨어 관련입니다.


1
계획된 중단을 시행 할 수 있습니까? 이러한 업데이트 중 하나가 트리거를 지우지 않고 집계를 업데이트하지 않으면 데이터가 잘못 될 수 있습니다.
Erik

실험실, 절차, 백신 및 환자에 대한 모든 정보를 단일 테이블에 넣는 것을 고려하고 있습니까? 나쁜 생각. 실행중인 쿼리 유형에 적합한 스타 스키마를 사용할 수 있습니다.
Michael Green

1
인덱싱 된 뷰를 만들었습니까? 이렇게하면 코드와 공급 업체 사이에 논리적 계층이 배치되므로 공급 업체가 아래에서 변경하면 뷰를 업데이트 할 수 있습니다. 또한 인덱싱 된 뷰는 미리 채워져 있으며 읽기 성능이 좋습니다. 이를 수행 할 때 고려해야 할 더 큰 고려 사항 중 하나는 공급 업체 데이터베이스 테이블의 쓰기 작업에 얼마나 많은로드가 필요한지입니다. 그러나 이것은 트리거 등을 사용하는 것보다 솔루션을 유지하는 것이 더 깨끗하고 유지하기 쉬울 것입니다.
Micah Nikkel

답장이 늦어 죄송합니다. 의견을 보내 주셔서 감사합니다. @Erik-예, 업데이트를 계획했으며 실행중인 일련의 체크리스트 스크립트를 통해 이전의 모든 변경 사항이 여전히 적용되는지 확인하므로 놀랄 일이 없으며 CREATE 스크립트를 유지합니다. 모든 트리거.
jreed121

@MichaelGreen-스타 스키마를 살펴볼 것이지만 왜 한 테이블에 모든 데이터를 저장하는 것이 나쁜 생각인지 궁금합니다. 응용 프로그램 환경은 VPN에서 완전히 격리되어 네트워크 외부에서는 액세스 할 수 없습니다. 테이블에 문제가 생기면 모든 것을 다시 쓸 수 있기 때문에 세상의 끝이 아닙니다. 이 테이블은 미션 크리티컬 한 데이터에 사용되지 않거나 최소한 데이터가 저장되는 유일한 장소 나 기본 장소는 아닙니다.
jreed121

답변:


8

내가 당신을 올바르게 이해했다면

  • 큰 타사 시스템이 있고
  • 당신은 그것에 대해 많은 제어권이 없습니다.
  • 이 타사 데이터베이스에서 직접 데이터를 읽는 복잡한 보고서를 작성합니다.
  • 쿼리는 타사 데이터베이스의 내부 구조에 따라 다릅니다.

나는 이렇게 접근한다 :

  • 내가 완전히 제어 할 수있는 별도의 데이터베이스를 설정하십시오.
  • 타사 데이터베이스에서 관련 테이블 및 열의 데이터를 읽고 내 데이터베이스에 삽입 / 업데이트하는 동기화 프로세스를 설정하십시오.
  • 데이터베이스의 안정적인 구조를 기반으로 복잡한 보고서를 개발하십시오.

이 경우 타사 시스템에 영향을주지 않고 데이터베이스의 구조 및 색인을 미세 조정하여 보고서의 성능을 향상시킬 수 있습니다. 원래 데이터 구조가 크게 변경되지 않으면 타사 데이터베이스가 변경 되어도 보고서에 대한 쿼리 논리가 변경되지 않습니다. 동기화 프로세스 만 조정해야합니다.

동기화 프로세스는 효과적으로 변환 프로세스입니다. 타사 데이터베이스의 데이터를 필요한 구조로 변환합니다. 이 변환 프로세스의 일부로 원래 타사 데이터베이스에있을 수있는 정규화 문제를 해결할 수 있습니다. 시스템의이 부분 만이 타사 시스템의 내부 구조를 알고 의존해야합니다. 기본 보고서와 기본 쿼리는 데이터베이스에만 의존합니다.

따라서 요점은-분리되어 타사 시스템의 내부에 의존하는 시스템 부분을 제한하는 것입니다.

최신 정보

실시간 요구 사항과 관련하여. BTW, 나는 항상 "실시간"의 정의는 "일부 작은 응답 시간"이 아니라 "보증 된 응답 시간"이라고 생각했다. 물론 응용 프로그램에 따라 다릅니다. 실제로는 변경 사항이 감지 된 순간에 두 개의 데이터베이스를 동기화하면 충분합니다. 사용자에게 화면에 보고서가 표시되고 일부 기본 데이터 변경 사항이 표시되면이 변경 사항을 반영하기 위해 보고서를 다시 실행해야합니다. 변경 사항을 폴링하거나 일부 이벤트 / 메시지를 청취 할 수 있지만 최신 변경 사항을 표시하려면 보고서 조회를 다시 실행해야합니다.

원래 테이블의 변경 사항을 캡처하기 위해 트리거를 작성하고 이러한 변경 사항을 하나의 일반 테이블에 작성하려고합니다. 따라서 의도 한대로 변경 사항을 캡처하지만 단일 테이블이 아닌 올바르게 정규화 된 테이블에 변경 사항을 작성하십시오.

따라서 이는 극단적 인 경우입니다. 타사 데이터 구조를 내부 데이터 구조로 변환하는 작업은 INSERT/UPDATE/DELETE타사 테이블 에서 실행되는 트리거에서 수행됩니다 . 까다로울 수 있습니다. 트리거 코드는 두 시스템의 내부 구조에 따라 다릅니다. 변환이 사소한 것이 아니라면 INSERT/UPDATE/DELETE실패 시점까지 원본 을 지연시킬 수 있습니다 . 트리거에 버그가 있으면 실패 시점까지 원래 트랜잭션에 영향을 줄 수 있습니다. 타사 시스템이 변경되면 트리거가 중단되어 타사 시스템의 트랜잭션이 실패 할 수 있습니다.

덜 극단적 인 경우. 트리거 코드를 더 간단하고 오류가 덜 발생하도록하려면 준비 / 감사 / 차이 테이블에 캡처 된 모든 변경 사항을 쓰려면 보류중인 변경 사항이 있다는 메시지를 플래그로 보내거나 보내십시오. 이러한 중개 테이블을 통해 변환을 수행하십시오. 여기서 중요한 것은 원래의 거래 범위를 벗어나는 변환 프로세스가 많이 발생할 수 있다는 것입니다.

언뜻보기에 그것은 질문의 원래 제안과 거의 같습니다. 그러나 차이점은 캡처-전체 테이블은 데이터를 일시적으로 만 보유합니다. 데이터의 양이 적습니다-변경된 내용; 단일 테이블 일 필요는 없습니다. 결국 데이터는 완전히 정규화 된 별도의 영구 테이블에 저장됩니다.이 테이블은 사용자가 완전히 제어 할 수 있으며 타사 시스템과 독립적이며 쿼리를 조정할 수 있습니다.


배치 전송 경로를 사용하는 경우 상당한 수의 트랜잭션 수 (하루 100K)로 변경 추적 (및 필요에 따라 변경 데이터 캡처)에 성공한 것입니다. 자체 준비 / 감사 / 차이 테이블을 구현하는 것보다 간단하며 응용 프로그램 코드 변경이나 트리거없이 배포 할 수 있습니다.
Michael Green

실제로 실시간에 접근 할 수있는 유일한 방법은 트리거 또는 CDC이기 때문에 스트리밍 또는 큐잉입니다. 큐 기반은 대기 시간과 비용 효율성을 절충합니다. 대기열을 빠르게 처리하는 방법에 시간이 소요됩니다. 대부분의 작업을 애플리케이션에서 비동기식으로 유지하고 사용자 트랜잭션에 대한로드를 줄입니다. 과거에는 Allscripts Sunrise EMR에 대해 병렬 C # 호출과 함께 대기열을 처리하는 서비스 로이 작업을 수행했습니다. 웨어 하우스에서 새로운 데이터를 처리하고 사용할 수있는 일반적인 대기 시간은 30 초 미만입니다.
Brad D

"실시간"을 너무 많이 언급했을 수도 있지만 밀리 초 또는 5 초에 대해서는 크게 신경 쓰지 않지만 직원들이 워크 플로를 추진하는 데 의존하는 많은 쿼리가 있습니다. 고객이 그들에게 무언가를 한 경우 (절차, 예방 접종 등) 단기간에이를 보여 주어야합니다. 전환은 사소하고 /하거나 전환이 아닙니다. 벤더 테이블의 변경에 대해 너무 걱정하지 않습니다. 벤더 테이블은 자주 변경되지 않으므로 어쨌든해야하지만 내 생각에는 수십 개의 보고서 / 쿼리보다 하나의 트리거를 업데이트 / 재 작성하는 것이 더 쉽다는 생각이었습니다. / SP. 모든 업데이트 후에 확인을 실행합니다.
jreed121

@ jreed121, 보고서보다 트리거를 업데이트 하는 것이 더 쉽다고 생각 합니다. 변경 사항을 캡처하기 위해 각 소스 테이블에 트리거가있을 수 있으므로 둘 이상의 트리거 일 수 있습니다. 여전히 캡처 된 모든 변경 사항을 하나의 거대한 비정규 화 된 테이블에 쓰려고하지 마십시오. 올바르게 정규화 된 테이블 세트에 씁니다. 보고서는 사용자가 제어하는 ​​정규화 된 테이블을 기반으로해야하며 변경 될 수있는 원래 테이블에 의존 해서는 안됩니다 .
블라디미르 바라 노프

3

복잡한 테이블과 쿼리를 변경하지 않고 가져 오기 단계를 조정할 수 있도록 표준화 된 테이블 세트에 배치하십시오. 그러나 여러 테이블이 필요하지만 인덱스가 좋은 데이터는 여전히 정규화되어야합니다.

다른 사람들이 언급했듯이 트리거를 사용하지 말고 일괄 동기화하십시오.

데이터가 정규화되고 올바르게 색인화 될 때 많은 조인에 대해 걱정하지 않아도되므로 상당한 비용이나 관리 부담이 발생하지 않습니다.

데이터웨어 하우스와 같은 것으로 비정규 화하는 시간은 예측할 수없는 데이터에 대해 다양한 유형의 쿼리를 만들 수 있어야 할 때입니다. 자체 단점과 오버 헤드가 있으므로 적절한 곳이 아니라 이동해야합니다.


3

나는 과거 24x7 제조 회사에서 이와 비슷한 상황에서 일했고 마침내 트랜잭션 복제를 사용하기로 결정했습니다. 가능하다 구성 DDL에 당신이 패치를 가입자로 변경 어떤 밀어 수 있도록 복제 할 수 있습니다. 분명히 모든 것에 장단점이 있으며 회사에 가장 적합한 것에 대해 무엇을 지원할 수 있는지 결정하기 위해 그것들을 평가해야합니다.

긍정적 인면에서 :

  1. "실시간"은 가입자의 네트워크 및 트랜잭션 커밋 성능으로 만 제한됩니다. 약간 높은 TPS 시스템을 사용한 경험에서 우리는 "실시간"데이터의 10 초 이내에 복제되었습니다.
  2. 작업 분리. 현재 한 서버에서 혼합 워크로드를 실행하고 있습니다. 이 두 가지 문제를 분리 할 수 ​​있다면 방정식에서 하나의 작업 부하를 제거하여 두 시스템 모두에서 성능 이점을 얻을 수 있습니다.
  3. 제어. 보고 워크로드에 맞게 인덱싱 / 통계 / 유지 보수를 수정할 수 있습니다.

그러나 단점이 있습니다.

  1. 비용. 다른 라이센스 및 더 많은 하드웨어 (가상 또는 기타)
  2. 복제. 제대로 설정되면 훌륭하게 작동하지만 그 시점에 도달하기가 번거로울 수 있습니다.
  3. 유지. 구조를 유해하게 변경하면 (예 : 인덱스 삭제) 스냅 샷이 적용될 때 (게시가 변경된 후 또는 기사가 변경된 후) 반환됩니다.

2

내 계획은이 모든 레코드를 하나의 "포괄"테이블에 기록하고 원래 테이블에 트리거를 작성하여이 집계 테이블에 레코드를 유지하는 것입니다.

트리거에는 너무 많은 문제가 있으므로 피해야합니다.

  • 트리거 오류로 인해 원래 트랜잭션이 중단 될 수 있습니다.
  • 여러 행 작업을 올바르게 처리하는 트리거는 쓰기가 어렵습니다.
  • 트리거는 반환 된 행 집합을 수정하여 클라이언트 응용 프로그램을 혼동시킬 수 있습니다 (예 : 트리거가 영향을받는 행 수를 재정의 함)
  • 한 트리거가 다른 트리거를 트리거하면 결과를 예측하기가 어렵습니다

더 나은 옵션은 주기적으로 데이터를 새 테이블에 복사하는 작업입니다. 보고서가 사본을 실행할 수 있습니다. 행을 복사하는 작업은 작성 및 유지 관리가 쉽고 타사 응용 프로그램의 작동에 영향을 줄 위험이 없습니다.


1. 트리거는 단순하므로 발생하는 오류는 최소화됩니다. 2. 트리거 자체는 여러 행을 처리하지 않으며 (즉, 트리거를 사용하여 테이블에서 업데이트 된 한 행은 다른 곳에서 여러 행을 업데이트하지 않음) 소스에서 한 번에 여러 행을 삽입 / 업데이트 / 삭제할 수 있습니다. 표-이것이 당신이 의미하는 것입니까? 3. 이것으로 처리 할 수 NOCOUNT없습니까? 4. 대상 테이블에 트리거가 없으며 다른 테이블에도 동일하게 보장 할 수 있습니다.
jreed121

말한 것처럼 이론적으로 트리거를 작동시킬 수 있습니다. 실제로는 절대로 그렇게하지 않습니다.
Andomar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.