여러 데이터베이스 / 서버를 사용하여 데이터와 상호 작용


18

지금까지 처리해야하는 모든 프로젝트는 단일 서버에서 단일 데이터베이스 만 필요했습니다. 확장이 필요한 프로젝트가 여러 데이터베이스 및 / 또는 서버로 이동하여로드를 관리하는 방법에 대해 자세히 알고 싶습니다. 나는 높은 확장 성을 알고 있지만 특히 주제에 대해 더 많이 읽을 수있는 일부 코드 예제 또는 추가 리소스에 관심이 있습니다.

예를 들어 :

  • 여러 데이터베이스의 두 테이블간에 조인이 어떻게 구성됩니까? (여기 코드 예제가 도움이 될 것입니다).
  • 어떤 데이터베이스에 어떤 테이블이 있는지 추적하기위한 특별한 전략이 있습니까?
  • 응용 프로그램 코드는 하나 이상의 데이터베이스가 여러 서버에 분산되어 있음을 알아야합니까? 그렇지 않은 경우 요청이 필터링되는 수준은 무엇입니까?
  • 1 데이터베이스 / 1 서버 설정을 넘어서는 시점은 언제입니까? 이렇게하는 것이 얼마나 흔한 일입니까?

이 질문은 데이터베이스 관리자 에게 더 잘 대답 할 수 있습니다 . 그래도 여기에 아무런 문제가 없으므로 DBA 모드를 확인하겠습니다. 거기에 적합한 경우 마이그레이션 하시겠습니까?
Adam Lear

@AnnaLear-답변에 따라 달라집니다. 이 시점에서 문제의 응용 프로그램 측면에 더 관심이 있으므로 지금은 더 좋을 것 같습니다.
VirtuosiMedia

@AnnaLear ack, 앱 특정 코드를 원하면 OP에 동의하십시오.
jcolebrand

답변:


13

좋아, 그것을 분해하자 :

  • 여러 데이터베이스의 두 테이블간에 조인이 어떻게 구성됩니까? (여기 코드 예제가 도움이 될 것입니다).

이것은 매우 간단합니다. SQL 개체에는 1-4 개의 부분 명명 규칙이 있습니다.

서버 이름. 데이터베이스 이름. 스키마 이름. 테이블 이름

모든 테이블이 동일한 데이터베이스에서 동일한 소유자 / 스키마로 동일한 서버에있는 경우 처음 세 부분을 무시하고 가장 익숙한 것을 사용할 수 있습니다.

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

테이블 중 하나가 다른 데이터베이스에 있고 둘 다 데이터베이스에 기본 스키마를 사용하는 경우 두 번째 테이블에 데이터베이스를 추가하기 만하면됩니다.

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

쿼리중인 데이터베이스와 다른 세 번째 데이터베이스에있는 경우 두 데이터베이스 이름을 명시 적으로 사용합니다.

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

다른 스키마 및 / 또는 소유자를 사용하게되면 다음에 스키마를 추가 할 수 있습니다.

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

마지막으로, 매우 신중하고 좋은 이유가 있다면 다른 서버에서 (보통 작은) 테이블을 조인 할 수 있습니다.

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • 1 데이터베이스 / 1 서버 설정을 넘어서는 시점은 언제입니까? 이렇게하는 것이 얼마나 흔한 일입니까? 어떤 데이터베이스에 어떤 테이블이 있는지 추적하기위한 특별한 전략이 있습니까?

이 두 가지를 함께 사용할 것입니다. 설계 / 비즈니스 / 기술적 제약으로 인해 더 많은 데이터베이스를 사용할 때까지 하나의 데이터베이스로 하나의 서버로 충분하다는 가정으로 시작하는 것이 좋습니다.

따라서 두 번째 질문에 먼저 대답하려면 일반적으로 별도의 데이터베이스가 있어야하는 이유가 있기 때문에 시스템의 디자인을 알고있는 것이 분명합니다.

언제 / 왜 단일 데이터베이스 이상으로 이동해야하는지에 대해. 일반적으로 비즈니스 규칙, 정치 및 / 또는 기술적 이유가 혼합되어 있습니다.

예를 들어, 내가 일하는 곳에서는 4 대의 서버에 16 개의 데이터베이스가 분산되어 있습니다. 우리는 MainDB, ImageDB, referencetableDB, HighvolumeTransactionDB, ReportingDB, StagingDB, ProcessingDB, ArchiveDB, FinancialDB를 가지고 있습니다. 왜 다른지 몇 가지 예를 들자면 :

  • FinancialDB, 민감한 정보
  • 이미지 DB, 특정 다른 스토리지 및 복구 요구 사항
  • ReferenceDB, 낮은 트랜잭션, 높은 읽기
  • 읽기 데이터가 많은 ReportingDB는 다른 많은 데이터와 달리 다양한 다른 환경으로 복원 / 복제해야합니다.
  • StagingDB, 영구적이지 않은, 우리가 더 잘 제어 할 수있는 강화 된 tempdb
  • MainDB는 다른 모든 DB와 인터페이스하지만 차등 백업이 필요하므로 ...
  • 백업을 적당한 크기로 유지하기 위해 HighVolumeTransaction 테이블 (상대적으로 일시적인)을 자체 DB에 저장합니다.
  • Archive, Main 및 Reporting에서 동일한 데이터가 많지만 보존 기간이 길고 조회가 더 어려워서 데이터를 깊이 파고 들었습니다. 이것이 여전히 Main / Reporting과 결합되면 시스템이 다운 될 수 있습니다.

응용 프로그램 코드는 하나 이상의 데이터베이스가 여러 서버에 분산되어 있음을 알아야합니까? 그렇지 않은 경우 요청이 필터링되는 수준은 무엇입니까?

넓은 의미에서 그들은 아마 할 것입니다. 최소한 데이터베이스 연결 문자열에서 어떤 서버를 가리키고 있는지 알아야합니다. 처리,보고, 메인 등

거기에서 실행하려면 데이터베이스 컨텍스트가 필요합니다. 일반적으로 응용 프로그램에 가장 많이 사용되는 응용 프로그램 일 수도 있고 응용 프로그램의 데이터베이스 일 / 서버 일의 원래 원본 일 수도 있습니다. 모든 호출에서 응용 프로그램이 명시 적으로 데이터베이스 컨텍스트를 전환하도록 할 수는 있지만 앱을 변경하지 않고 데이터베이스를 조정하기가 매우 어렵습니다.

일반적인 (또는 적어도 나의 일반적인) 방법은 항상 하나 또는 두 개의 기본 데이터베이스를 통해 액세스하는 것입니다.

그런 다음 저장 프로 시저를 통해 데이터베이스와 인터페이스하여 필요에 따라 다른 데이터베이스에 대한보기를 작성하십시오.

그래서 설명하기 위해 :

고객의 인구 통계 학적 정보, 판매 데이터 및 신용 잔고를 얻으려고한다고 가정하고 MainDB의 원래 세 테이블에 분산되어 있다고 가정하겠습니다.

따라서 앱에서 전화를 겁니다.

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

대박. 그러나 이제 columname을 변경하거나 테이블 이름을 바꾸거나 테이블을 이동할 때마다 앱 코드를 업데이트해야합니다. 대신
클라이언트, 판매, AccountReceivables 뷰 만들기 (Select *를 사용하지 않지만 여기서는 데모 중입니다)라는 두 가지 작업을 수행합니다.

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

그런 다음 스토어드 프로 시저 spGetClientSalesAR도 작성합니다.

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

그리고 앱이 그것을 호출하게하십시오.

이제 저장된 프로 시저의 인터페이스를 변경하지 않는 한 백엔드 데이터베이스에서 확장 또는 축소하기 위해 필요한 모든 작업을 수행 할 수 있습니다.

극단적으로, 나는 이전 MainDB를 여러 가지 쉘 저장 프로 시저와 뷰로 만들 수 있었으므로 우리가 만든 뷰 아래에서 다음과 같이 보입니다.

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

그리고 앱은 차이를 알지 못할 것입니다 (빠른 파이프와 잘 준비된 데이터를 가정 할 때).

분명히 모든 것이 이런 식으로 계획되었다고 말하면 극단적이며 거짓말을 할 것입니다. 그러나 리팩토링하는 동안 저장 프로 시저 / 뷰를 사용하더라도 응용 프로그램이 겸손한 하나의 데이터베이스 / 하나의 서버에서 성장함에 따라 많은 유연성이 허용됩니다 처음.


TetonSig-답변 주셔서 감사합니다. 나는 당신에게 완전한 현상금을 수여하기 위해 제 시간에 질문으로 돌아갈 수 없었습니다 (나는 여행 중이었습니다). 나는 그 질문에 대한 새로운 현상금을 만들었고 24 시간 안에 당신에게 그것을 수여 할 수 있습니다.
VirtuosiMedia

와우 감사합니다. 알겠습니다. 질문에 대답하는 것은 많은 재미였습니다.
TetonSig

5

웹 세계에서 여러 데이터베이스 서버를 만난 주요 방법은 (PHP로 태그가 지정되어 있기 때문에) 하나의 '마스터'(쓰기) 데이터베이스와 하나 이상의 복제 된 '슬레이브'(읽기) 데이터베이스가있는 설정입니다. . 데이터베이스 쓰기는 '마스터'데이터베이스에 대해 수행됩니다. 해당 데이터베이스의 내용은 거의 실시간으로 '슬레이브'서버에 복제됩니다. 그런 다음 쿼리, 특히 집중적 인 보고서는로드를 해당 서버로 이동하기 위해 '슬레이브'데이터베이스 중 하나에 대해 실행됩니다. 특정 설정은 읽기는 많지만 쓰기는 많지 않은 응용 프로그램에 가장 적합합니다. 결코 물건을 정리하는 유일한 방법은 아닙니다.


3

여러 데이터베이스의 두 테이블간에 조인이 어떻게 구성됩니까? (여기 코드 예제가 도움이 될 것입니다).

그들은 아니야. NoSQL 데이터베이스는 "조인"을 전혀하지 않으며 RDBMS 서버에서 SQL 조인을 수행 할 수 있다고 해도 성능을 중요하게 생각하고 싶지는 않습니다 ( 분산 컴퓨팅의 오류 ).

어떤 데이터베이스에 어떤 테이블이 있는지 추적하기위한 특별한 전략이 있습니까?

관계형 / SQL 데이터베이스에서 파티셔닝은 일반적으로 다른 디스크에있는 다른 파일을 사용하여 단일 서버 / 데이터베이스의 범위 내에서 수행됩니다. 거의 수평 적으로 수평 확장 솔루션이란 모든 데이터베이스에 모든 테이블이 있고 모든 데이터가 원하는 위치에 도달 할 수 있도록 일종의 트랜잭션 미러링, 복제 또는 사용자 지정 최종 일관성 솔루션을 가지고 있음을 의미합니다.

실제로 데이터베이스를 물리적이 아닌 논리적으로 분할하는 경우 DAL 또는 ORM에 정의 된 매핑은 어떤 데이터베이스에 어떤 테이블이 있는지 선언합니다.

NoSQL 데이터베이스는 파티셔닝 솔루션의 혼합입니다. 때로는 분할 된 "테이블"(또는 더 일반적으로 "컬렉션")입니다. 다른 경우에는 "행"(또는 "문서")입니다. 어떤 경우에는 HBase와 같은 열 지향 데이터베이스에서와 같이 실제로 입니다. 그것은 당신이 사용하는 기술에 전적으로 달려 있습니다. 이 모든 것이 공통적으로 갖는 한 가지는 엔진 자체가 모든 것을 추적하므로 문서 또는 행을 요청하기 만하면됩니다.

물론 여러 데이터베이스를 만드는 것이 아니라 샤딩 기능을 실제로 사용한다고 가정합니다. 당신이 후자를하고 있다면, 당신은 스스로하고 있습니다.

응용 프로그램 코드는 하나 이상의 데이터베이스가 여러 서버에 분산되어 있음을 알아야합니까? 그렇지 않은 경우 요청이 필터링되는 수준은 무엇입니까?

서로 다른 논리적 데이터베이스라면 그렇습니다. 물리적 으로 만 분산되어 있으면 특정 데이터베이스가 기본적으로 샤딩을 지원하거나 부하 분산 솔루션 (SQL 데이터베이스의 경우)을 사용한다고 가정하지 않습니다. 또한 모든 작업이 상태 비 저장이라고 가정합니다. 수평 스케일링을 원하면 ACID를 포기해야합니다.

1 데이터베이스 / 1 서버 설정을 넘어서는 시점은 언제입니까? 이렇게하는 것이 얼마나 흔한 일입니까?

한 서버에서 가능한 모든 것을 최적화하고 I / O로드의 제약으로 인해 충분한 성능을 발휘할 수없는시기입니다. 질문을해야한다면 너무 빠릅니다.

적절한 RDBMS 제품 (Oracle, SQL Server)의 성능 문제는 디자인 불량, 인덱싱 불량, 쿼리 불량, 잠금 경합 등으로 인해 더 자주 발생합니다. 이 제품들은 엄청나게 수직으로 확장 할 수 있습니다. 따라서 성능 문제가 하위 수준 설계 / 구현이 아니라 하드웨어 제한으로 인한 것임을 확신 할 때 "1 데이터베이스 / 1 서버 설정을 넘어서 이동"을 고려해야합니다 .

또는 일부 사람들이 분산 데이터베이스로 전환하는 또 다른 이유는 라이센스 비용으로 많은 돈을 지불 할 준비가되지 않았고 애플리케이션 복잡성을 증가시키기 위해 저렴한 비용으로 거래하기 위해 SQL을 버리고 자하는 선택 일 때입니다. 소프트웨어 스타트 업이지만 일반적으로 회사 부문에는 해당되지 않는 경우에 대한 완전한 이유입니다.


+1-NoSQL을 실제로 고려하지는 않았지만 모두 똑같이 도움이됩니다. 감사.
VirtuosiMedia

1

데이터베이스에 대한 세 가지 주요 유형의 복제 구성이 있습니다.

  • 주인 노예
  • 마스터 마스터
  • 일치

마스터-슬레이브 예 : MySQL 마스터 + MySQL 슬레이브, MongoDB

마스터 마스터 예 : CouchDB, Cassandra, Riak

합의 예 : ScalienDB

... 몇 가지를 말하면됩니다.

이들은 다른 특성을 가지고 있습니다. 마스터-슬레이브 구성을 사용하면 마스터 노드가 데이터 무결성을 담당하는 반면 슬레이브 노드는 읽기 요청을 매우 빠르게 처리하면서 마스터를 최대 속도로 따라 잡을 수 있습니다. 모든 쓰기가 마스터에 전달되기 때문에 상대적으로 느린 단일 작성자가 많은 독자를 차단하기 때문에 경쟁이 발생하지 않습니다. 반면에 슬레이브 서버는 일관되며 트랜잭션 격리 보장을 얻지 못합니다. 오직 마스터 에게서만 읽습니다. (추가 정보 : ACID vs BASE, 트랜잭션 격리 수준, 데이터베이스 복제, MVCC / 절연 : 스냅 샷, 트랜잭션 복제)

Master-Master는 항상 쓰기를 허용하므로 사실에 대한 여러 권한을 갖게됩니다. 응용 프로그램이 수행하는 작업에 따라 문제가 될 수도 있고 아닐 수도 있지만 충돌하는 데이터를 쓰는 경우 다음에 응용 프로그램 논리와 병합 해야하는 키 / 행 / 열을 읽을 때 여러 결과가 나타날 수 있습니다. 데이터베이스에 다시 저장하십시오. (추가 읽기 : CAP 정리, CouchDB 복제, Riak 복제, 일관된 해싱, Bitcask & StormDB, 네트워크 분할에 대한 MongoDB가있는 쿼럼, 병합 해결 전략)

Scalien과 같은 노드 간 복제 기능이있는 합의 기반 데이터베이스는 쓰기시 항상 일관성이 있지만 쓰기를 ACK하기 전에 여러 메시지를 교환해야합니다. 빠른 이더넷이 있고 ACK하기 전에 디스크에 쓸 필요가없는 경우에는 큰 문제가되지 않습니다. 최소 3 개의 서버가 별도의 전원 공급 장치 (하나는 다른 전원 공급 장치가있는 다른 서버 랙에있는 경우)가 아닙니다. 다른 두 개는 디스크에 저장되었는지 확인합니다). (추가 정보 : PAXOS, PAXOS COMMIT, 분산 트랜잭션이있는 2 단계 커밋, 3 단계 커밋)

기타 추가 자료 : (도서 : 'Distributed Computing의 요소', 벡터 클록, 버전 벡터, 매트릭스 벡터, 논리 클록, 베이커리 알고리즘, 인터벌 트리 클록, 액터 및 반응 형 프로그래밍 및 리액터, 소프트웨어 트랜잭션 메모리, 트랜스 액터, AKKA, Stact, 분산 컴퓨팅, 가십 프로토콜의 오류, Cassandra의 엔트로피 가십 프로토콜 확장, 분산 해시 테이블, 분산 설정에서 데이터 병합에 대한 논문, ZooKeeper 아키텍처, "비동기 프로토콜"에 대한 InfoQ 표시, HBase 아키텍처, MapReduce 용지, Amazon Dynamo 용지 모든 NoSQL, 큐잉, rabbitmq 고 가용성 클러스터링을 시작했습니다)

나는 생각할 음식을 주었으면 좋겠다. :). 이 소식에 대한 트윗을 원하시면 트위터 @henrikfeldt에서 저를 팔로우하십시오.


1

여기 확장성에 대한 또 다른 관점이 있습니다.

데이터가되는 것이 무엇을 의미하는지, 행동을 갖는 것이 무엇을 의미하는지, 그리고 애플리케이션 로직을 갖는 것이 무엇을 의미하는지 논의 해 봅시다.

일반적으로 기업 응용 프로그램 등의 영역에 투자 할 때 계층화 개념에 노출 될 수 있습니다. 물론, 계층화는 네트워킹 스택 (ISO 모델), 그래픽 (Photoshop) 또는 SOA (서비스는 형제 또는 자식을 호출 할 수 있지만 부모는 절대 호출 할 수 없음)와 같은 컴퓨터에서 사용됩니다.

그러나 'GUI', 'Business Logic Layer'및 'Data Access Layer'의 유형에 관계없이 남용 된 특정 유형의 계층화. 예, 공산주의는 원칙적으로는 좋지만 아이디어는 원칙적으로는 좋지만 실제로는 그렇지 않습니다.

왜 그런지 살펴 보자. 내가 사용할 인수는 커플 링에 관한 것입니다. 한 레이어에서 다른 레이어의 포인트에 닿는 포인트. 사람들이 들어가는 기본 엔터 프라이즈 모드에서 n 계층 일명 계층 응용 프로그램을 만들 때마다 그들은 계층 사이에 너무 많은 접촉 지점을 만듭니다.

핵심은 레이어를 서로 바꿔서 사용할 수 있다는 것입니다. 그러나 그들은 아닙니다! 왜? 모든 호출 사이트 커플 링 때문에.

대신 네트워크가 분리 된 이유를 살펴보십시오! 인터페이스는 열린 소켓을 가리키는 단일 파일 포인터를 통한 바이트 스트림이기 때문에! ISO 모델의 모든 레이어는 '책임 체인'이라는 디자인 패턴이 객체 방향과 같습니다! 각 계층은 기본 계층의 데이터 의미를 몰라도 기본 계층을 래핑합니다.

데이터 패키지가 맨 아래의 이더넷 및 원시 전기 신호를 향할 때 자체 메시지 봉투 만 알고있는 특정 바이트 배치 (batch of bytes) 만 알고있는 계층에 의해 계속 랩핑됩니다. 그리고 다른 것은 없습니다. 패키지 내용에 따라 호출 경로를 변경할 필요가 없습니다.

이것을 n-tier와 대조하여 데이터베이스로가는 동안 계층을 통과하는 '통화'에서 애플리케이션 계층의 통화 경로를 변경해야합니다. 예를 들어 '금 고객'은 다형성으로 '일반 고객'의 상위 집합입니다 우리는 '서브 클래스 당 테이블'을 사용하기 때문에 이제 데이터 (엔티티)가 계층을 통과하고 있다는 것을 알아야합니다. 소위 '비즈니스 로직 계층'과 실제로 저장을 수행하는 데이터 계층 모두에서.

컴퓨팅 관점에서 확장 성도없고 최적도 아닙니다.

왜 확장 할 수 없습니까? 아키텍처가 결합 된 후에도 여전히 많은 노드로 확장하려고했던 것과 동일한 이전 DB 내에 있습니다! 그러나이를 위해서는 ACID가 필요하기 때문에 세 번째 엔터티 (데이터 개체)는 트랜잭션을 수행하는 단일 데이터베이스에 있어야합니다!

그렇습니다. 다른 방법은 무엇입니까?

서비스 지향 아키텍처 인 'SOA'라는 증오 약어가 있습니다. 물론, Tomas Erls of the world 는 XML과 SOAP 대신 모든 레이어를 구현하게합니다.

위의 모든 이유로 인해, 이것은 잘못된 길입니다. 위에서 설명한 것처럼 응용 프로그램 계층에 연결하는 것처럼 XML 프록시에 자신을 연결하기 때문입니다.

대신, 메시징을 사용하고 기능을 구현하는 모든 것이 들어 지도록하십시오. 그런 다음 서비스 영역은 보낼 수있는 메시지 목록이되며 작업을 서비스 외관에 연결하지 않았습니다. 또한 다른 라우팅 메커니즘이 올바른 소비자에게 라우팅한다는 메시지를 게시하기 만하면 이러한 작업을 구현하는 응용 프로그램이나 엔드 포인트를 알 필요조차 없습니다!

수행하려는 실제 작업에서 서비스 파사드를 분리 했으므로 이제 여러 서비스를 추가 할 수 있습니다. 사실, 이것이 Netflix가하는 방식입니다. 이러한 프리젠 테이션에서 찾아 보게 http://www.slideshare.net/adrianco/global-netflix-platform을 . http://www.slideshare.net/adrianco/global-netflix-platform . 그들은 좋다!


0

새로운 SQL (ACID) 데이터베이스 탄성 스케일링 속성을 가지고 주장이다 베타는. 지금 무료 베타 프로그램이 진행 중이며 NuoDB라고합니다.

분명히 단일 스레드 시스템에서도 MySQL보다 성능이 뛰어나지 만 특정 벤치 마크에서는 70 + 인스턴스로 행복하게 확장됩니다.


단일 스레드? 그렇다면 어떻게 관련 벤치 마크입니까?
Henrik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.