스키마 및 데이터 모델

데이터 모델 요약

Cloud Spanner 데이터베이스는 하나 이상의 테이블을 포함할 수 있습니다. 테이블는 행, 열, 값으로 구성되어 있고 기본 키를 포함한다는 점에서 관계형 데이터베이스 테이블와 비슷합니다. Cloud Spanner의 데이터는 강력한 유형입니다. 즉, 각 데이터베이스에 스키마를 정의해야 하고, 이 스키마가 각 테이블에서 각 열의 데이터 유형을 지정해야 합니다. 허용되는 데이터 유형에는 스칼라와 배열 유형이 있습니다. 자세한 내용은 데이터 유형을 참조하세요. 테이블에서 하나 이상의 보조 색인을 정의할 수도 있습니다.

상하 테이블 관계

Cloud Spanner에서 상하 관계를 정의하는 방법에는 테이블 인터리브 처리외래 키 등 두 가지가 있습니다.

Cloud Spanner의 테이블 인터리브 처리는 하위 테이블의 기본 키에 상위 테이블의 기본 키 열이 포함된 여러 상하 관계에 적합합니다. 하위 행과 상위 행을 동일한 위치에 배치하면 성능이 크게 향상될 수 있습니다. 예를 들어 Customers 테이블와 Invoices 테이블이 있는데 애플리케이션이 특정 고객의 모든 인보이스를 자주 가져온다면 InvoicesCustomers의 하위 테이블로 정의할 수 있습니다. 이렇게 하면 논리적으로 독립된 2개의 테이블 사이에 데이터 지역성 관계를 선언하게 됩니다. 즉, Cloud Spanner에게 하나 이상의 Invoices 행을 하나의 Customers 행과 함께 물리적으로 저장하라고 명령하는 것입니다.

인터리브 처리에 대한 자세한 내용은 아래의 인터리브 처리된 표 만들기를 참조하세요.

외래 키는 보다 일반적인 상하 솔루션이며 추가 사용 사례를 해결합니다. 기본 키 열로 제한되지 않으며 테이블에는 여러 외래 키 관계가 일부 관계의 상위 요소와 다른 관계의 하위 요소 모두로 포함될 수 있습니다. 그러나 외래 키 관계가 스토리지 레이어에서 테이블의 동일한 위치를 암시하지 않습니다.

외래 키와 인터리브 처리된 테이블의 비교에 대한 자세한 내용은 외래 키 개요를 참조하세요.

기본 키

Cloud Spanner에 어느 Invoices 행을 어느 Customers 행과 함께 저장하라고 명령하려면 어떻게 해야 할까요? 테이블의 기본 키를 사용하면 됩니다. 모든 테이블에는 기본 키가 있으며 이 기본 키는 해당 테이블의 0개 이상의 열로 구성될 수 있습니다. 한 테이블을 다른 테이블의 하위 요소로 선언할 경우, 상위 테이블의 기본 키 열이 하위 테이블의 기본 키 접두사가 됩니다. 즉, 상위 테이블의 기본 키가 N개의 열로 구성되어 있다면 하위 테이블 각각의 기본 키도 똑같이 N개의 열로 구성되어야 하며 순서와 시작 열도 동일해야 합니다.

Cloud Spanner는 기본 키 값을 기준으로 정렬된 순서로 행을 저장하되, 동일한 기본 키 프리픽스를 공유하는 상위 행 사이에 하위 행을 삽입합니다. 이렇게 기본 키 측정기준에 따라 상위 행 사이에 하위 행을 삽입하는 것을 인터리브 처리라고 하며, 하위 테이블을 인터리브 처리된 테이블이라고도 합니다. 아래의 인터리브 처리된 테이블 만들기에서 인터리브 처리된 행에 대한 설명을 참조하세요.

요약하자면, Cloud Spanner는 관련된 테이블의 행을 물리적으로 같은 장소에 배치할 수 있습니다. 아래의 스키마 예는 이 같은 물리적 배치가 어떤 모습인지 보여줍니다.

기본 키 선택하기

기본 키는 테이블의 각 행을 고유하게 식별합니다. 테이블의 기존 행을 업데이트하거나 삭제하려면 테이블에 하나 이상의 열로 구성된 기본 키가 있어야 합니다. (기본 키 열이 없는 테이블에는 행이 1개만 있을 수 있습니다.) 애플리케이션에 이미 기본 키로 사용하기에 적합한 필드가 있는 경우가 있습니다. 예를 들어 위에서 예로 든 Customers 테이블에에서 애플리케이션이 제공한 CustomerId는 기본 키로 적합할 수 있습니다. 또는 행을 삽입할 때 사용자가 생성하는 고유한 INT64 값과 같은 기본 키를 생성해야 하는 경우가 있을 수 있습니다.

어떤 경우이든 기본 키를 선택할 때는 핫스팟을 만들지 않도록 주의해야 합니다. 예를 들어, 단조 증가하는 정수가 포함된 레코드를 키로 삽입할 경우 항상 키 공간 끝에 삽입됩니다. 이는 바람직하지 않은 방식입니다. Cloud Spanner는 키 범위를 기준으로 서버 간에 데이터를 구분하기 때문에 단일 서버에서 삽입이 이루어져서 핫스팟이 생성되기 때문입니다. 여러 서버로 부하를 분산시켜 핫스팟을 피할 수 있는 다음과 같은 방법이 있습니다.

데이터베이스 분할

테이블 간에 상하 관계 계층을 최대 7개까지 정의할 수 있습니다. 즉, 논리적으로 독립된 7개 테이블의 행을 같은 장소에 배치할 수 있습니다. 테이블의 데이터 크기가 작은 경우, 하나의 Cloud Spanner 서버로 데이터베이스를 처리할 수 있습니다. 그러나 관련 테이블이 많아져서 각 서버의 리소스 한도에 도달하면 어떻게 될까요? Cloud Spanner는 분산 데이터베이스로, 사용자의 데이터베이스가 증가함에 따라 '분할'이라고 하는 단위로 데이터를 나눕니다. 각 분할은 독립적으로 서로 간에 이동할 수 있으며 여러 물리적 위치에 있는 여러 서버에 할당될 수 있습니다. 분할이란 기본 키에 따라 행의 순서가 정해지는 최상위 수준(즉, 인터리브 처리되지 않은) 행의 범위로 정의됩니다. 이 범위의 시작 키와 종료 키를 '분할 경계'라고 합니다. Cloud Spanner는 분할 경계를 자동으로 추가하고 삭제하며, 이에 따라 데이터베이스 내 분할 수가 바뀝니다.

Cloud Spanner는 부하에 따라 데이터를 분할합니다. 즉, 한 분할 내의 여러 키 사이에 읽기 또는 쓰기 부하가 많이 분산된 것을 감지하면 자동으로 분할 경계를 추가합니다. Cloud Spanner는 계층의 루트에 있는 표(즉, 상위 표 안에 인터리브 처리되지 않은 표)의 행 사이에서만 분할 경계를 설정할 수 있기 때문에 사용자가 데이터가 분할되는 방식을 일부 제어할 수 있습니다. 또한 인터리브 처리된 테이블의 행은 상위 테이블에 있는 해당 행과 분리될 수 없습니다. 인터리브된 테이블의 행은 동일한 기본 키 접두사를 공유하는 상위 테이블의 행과 함께 정렬된 기본 키 순서로 저장되기 때문입니다. (인터리브 처리된 테이블의 계층 만들기에서 인터리브 처리된 행에 대한 설명을 참조하세요.) 따라서 사용자는 상하 테이블 관계를 정의하고 관련 테이블의 행에 기본 키 값을 설정하여 데이터가 내부에서 분할되는 방식을 제어할 수 있습니다.

부하 기반 분할

Cloud Spanner가 읽기 핫스팟을 완화하기 위해 부하 기반 분할을 수행하는 방법에 대한 예로, 데이터베이스에 테이블의 다른 모든 행보다 더 자주 읽히는 10개의 행이 있다고 가정해 보겠습니다. 해당 테이블이 데이터베이스 계층의 루트에 있는 한(즉, 인터리브 처리된 테이블이 아닌 한), Cloud Spanner는 10개 행 사이에 분할 경계를 추가하여 행을 읽을 때마다 단일 서버의 리소스가 소비되지 않고 각 행이 서로 다른 서버에서 처리되도록 할 수 있습니다.

일반적으로 스키마 디자인 권장사항을 따를 경우, Cloud Spanner는 인터리브 처리되지 않은 테이블의 행을 대상으로 하는 읽기에 대한 핫스팟을 완화하여 인스턴스의 리소스가 포화되거나 더 이상 새로운 분할 경계를 추가할 수 없을 때까지 읽기 처리량이 몇 분마다 개선되도록 할 수 있습니다(단일 행과 인터리브 처리된 하위 요소만 처리하는 분할이 있기 때문).

스키마 예

아래의 스키마 예는 상하 관계를 사용하거나 사용하지 않고 Cloud Spanner 테이블을 만드는 방법을 보여주며 이와 관련한 실제 데이터 레이아웃을 보여줍니다.

테이블 만들기

음악 애플리케이션을 만드는 중에 가수 데이터 행을 저장하는 간단한 표가 필요하다고 가정해 보겠습니다.

행이 5개이고 열이 4개인 Singers 표.

간단한 Singers 테이블 내 행의 논리 뷰. 기본 키 열은 굵은 선 왼쪽에 표시됩니다.

이 테이블은 굵은 선 왼쪽에 SingerId라는 기본 키 열이 하나 있으며 행, 열, 값으로 구성되어 있습니다.

다음과 같은 Cloud Spanner 스키마로 이 테이블을 정의할 수 있습니다.

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

이 스키마 예시에서 다음 사항에 주목하세요.

  • Singers는 데이터베이스 계층의 루트에 있는 테이블입니다(다른 테이블의 하위 요소로 정의되지 않았기 때문).
  • 기본 키 열에는 보통 NOT NULL이라는 주석이 추가됩니다. 단, 키 열에 NULL 값을 허용하려면 이 주석을 생략할 수 있습니다. 자세한 내용은 키 열을 참조하세요.
  • 기본 키에 포함되지 않은 열을 키가 아닌 열이라고 하며 이 열에는 NOT NULL 주석이 선택적으로 추가될 수 있습니다.
  • STRING 또는 BYTES 유형을 사용하는 열은 필드에 저장될 수 있는 최대 유니코드 문자 수를 나타내는 길이와 함께 정의되어야 합니다. 자세한 내용은 스칼라 데이터 유형을 참조하세요.

Singers 테이블의 실제 행 레이아웃은 어떤 모습일까요? 아래의 다이어그램은 인접한 기본 키로 저장된(즉, 기본 키의 정렬 순서에 따라 저장된) Singers 테이블의 행을 보여줍니다(즉, 'Singers(1)' 다음에 'Singers(2)'가 오는 순서이며 'Singers(1)'은 Singers 테이블에서 1로 키가 지정된 행을 나타냄).

인접한 키 순서로 저장되는 표 내 행의 예시.

각 분할이 여러 서버에서 처리되도록 하는 분할 경계의 예시를 보여주는 Singers 테이블의 실제 행 레이아웃.

또한 Singers는 데이터베이스 계층의 루트에 있기 때문에 위의 그림은 Singers의 모든 행 사이에서 나타날 수 있는 분할 경계의 모습을 보여주기도 합니다. 또한 여러 서버에 할당된 분할의 데이터와 Singers(3)Singers(4)로 키가 지정된 행 사이의 분할 경계 예시도 보여줍니다. 즉, 이 테이블이 커짐에 따라 Singers 데이터의 행이 여러 위치에 저장될 수 있습니다.

여러 테이블 만들기

이제 음악 애플리케이션에 각 가수의 앨범에 대한 몇 가지 기본적인 데이터를 추가하려는 경우를 가정해 보겠습니다.

행이 5개이고 열이 3개인 Albums 표.

Albums 테이블 내 행의 논리 뷰. 기본 키 열은 굵은 선 왼쪽에 표시됩니다.

Albums의 기본 키는 각 앨범을 해당 가수와 연결하는 SingerIdAlbumId라는 2개의 열로 구성됩니다. 다음의 스키마 예시에서는 AlbumsSingers 테이블 모두를 데이터베이스 계층의 루트에 정의하여 이 둘을 형제 테이블로 만듭니다.

-- Schema hierarchy:
-- + Singers (sibling table of Albums)
-- + Albums (sibling table of Singers)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId);

SingersAlbums 행의 실제 레이아웃은 이 다이어그램과 같은 모습이며, 인접 기본 키로 Albums 테이블의 행이 저장된 후 인접 기본 키로 Singers의 행이 저장됩니다.

실제 행 레이아웃: Albums와 Singers 행이 각각 키 값으로 저장됨

Singers 테이블와 Albums 테이블의 실제 행 레이아웃. 둘 다 데이터베이스 계층의 루트에 있음.

위의 스키마에서 한 가지 중요한 점은 Singers 테이블과 Albums 테이블은 최상위 수준의 테이블이기 때문에 Cloud Spanner가 둘 사이에 데이터 지역성 관계를 가정하지 않는다는 점입니다. 데이터베이스가 커짐에 따라 Cloud Spanner는 위에 표시된 모든 행 사이에 분할 경계를 추가할 수 있습니다. 즉, Albums 테이블의 행이 Singers 테이블의 행과 다른 분할에 위치할 수 있고 두 분할이 서로 간에 독립적으로 이동할 수 있습니다.

애플리케이션의 필요에 따라 Albums 데이터가 Singers 데이터와 다른 분할에 위치하도록 허용해도 좋습니다. 그러나 애플리케이션이 특정 가수의 모든 앨범에 대한 정보를 자주 검색해야 할 경우, AlbumsSingers의 하위 테이블로 만들어서 기본 키 측정기준에 따라 두 테이블의 행을 같은 위치에 배치하는 것이 좋습니다. 다음의 예시에서는 더 자세히 설명해줍니다.

인터리브 처리된 테이블 만들기

음악 애플리케이션을 설계하면서 이 앱이 특정 기본 키의 Singers 테이블과 Albums 테이블 행에 자주 액세스해야 한다는 것을 알게 되었다고 가정해 보겠습니다(예: Singers(1) 행에 액세스할 때마다 Albums(1, 1) 행과 Albums(1, 2) 행에도 액세스해야 함). 즉, SingersAlbums가 긴밀한 데이터 지역성 관계를 가져야 합니다.

AlbumsSingers 테이블의 하위 요소 또는 '인터리브 처리된' 요소로 만들어서 이 같은 데이터 지역성 관계를 선언할 수 있습니다. 기본 키에서 언급했듯이, 인터리브 처리된 테이블은 사용자가 다른 테이블의 하위 요소로 선언하여 하위 테이블의 행을 관련된 상위 행과 물리적으로 함께 저장하려는 경우에 사용하는 테이블입니다. 위에서 언급한 바와 같이 하위 테이블의 기본 키 프리픽스가 상위 테이블의 기본 키가 되어야 합니다.

아래 스키마에서 굵게 표시된 선은 AlbumsSingers의 인터리브 처리된 테이블로 만드는 방법을 보여줍니다.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

이 스키마에 대한 참고 사항:

  • 하위 테이블 Albums의 기본 키 프리픽스인 SingerId는 상위 테이블 Singers의 기본 키이기도 합니다. 이러한 설정은 SingersAlbums가 같은 계층 수준에 있다면 필요 없겠지만 이 스키마에서는 AlbumsSingers의 하위 테이블로 선언되었으므로 필요합니다.
  • ON DELETE CASCADE 주석은 상위 테이블의 행이 삭제되면 이 테이블에 있는 하위 행도 자동으로 삭제된다는 뜻입니다(즉, 동일한 기본 키로 시작되는 모든 행). 그러나 하위 테이블에 이 주석이 없거나 주석이 ON DELETE NO ACTION인 경우, 하위 행을 먼저 삭제해야 상위 행을 삭제할 수 있습니다.
  • 인터리브 처리된 행은 우선 상위 테이블의 행을 기준으로 정렬된 다음 상위 요소의 기본 키를 공유하는 하위 테이블의 인접 행을 기준으로 정렬됩니다. 즉, 'Singers(1)', 'Albums(1, 1)', 'Albums(1, 2)'의 순서입니다.
  • 분할은 Singers 테이블의 행 사이에만 삽입될 수 있기 때문에 이 데이터베이스가 분할될 경우 각 가수와 관련 앨범 데이터의 데이터 지역성 관계가 유지됩니다.
  • 하위 행을 삽입하려면 먼저 상위 행이 있어야 합니다. 상위 행은 이미 데이터베이스에 있거나 동일한 트랜잭션에서 하위 행을 삽입하기 전에 삽입할 수 있습니다.

실제 행 레이아웃: Albums 행이 Singers 행 사이에 인터리브 처리됨

Singers와 그 하위 테이블인 Albums의 실제 레이아웃.

인터리브 처리된 테이블의 계층 만들기

SingersAlbums 간의 상하 관계를 추가 하위 테이블로 확장할 수 있습니다. 예를 들어 각 앨범의 트랙 목록을 저장하기 위해 Albums의 하위 테이블로 Songs라는 인터리브 처리된 테이블을 만들 수 있습니다.

행이 6개이고 열이 4개인 Songs 표.

Songs 테이블 내 행의 논리 뷰. 기본 키 열은 굵은 선 왼쪽에 표시됩니다.

Songs는 해당 계층에서 그 위에 있는 테이블의 모든 기본 키로 구성된 기본 키를 가져야 합니다(즉, SingerIdAlbumId).

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)
--     + Songs (interleaved table, child table of Albums)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE TABLE Songs (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  TrackId      INT64 NOT NULL,
  SongName     STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
  INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

인터리브 처리된 행의 실제 뷰는 가수와 앨범, 노래 데이터 사이에 데이터 지역성 관계가 유지되는 것을 보여줍니다.

실제 행 레이아웃: Songs가 Albums 안에 인터리브 처리되고 Albums는 Singers 사이에 인터리브 처리됨

인터리브 처리된 테이블의 계층을 형성하는 Singers, Albums, Songs 테이블의 실제 행 레이아웃.

요약하자면, 상위 테이블과 모든 하위 테이블은 스키마 내에서 테이블의 계층을 형성합니다. 계층 내의 각 테이블은 논리적으로 독립되어 있지만 이런 방식으로 테이블을 물리적으로 인터리브 처리하면 테이블을 효과적으로 미리 결합하여 관련 행에 함께 액세스할 수 있고 디스크 액세스를 최소화함으로써 성능을 개선할 수 있습니다.

가능하다면 인터리빙된 테이블 내의 데이터를 기본 키로 조인합니다. 인터리브 처리된 모든 행은 상위 행과 동일한 분할에 물리적으로 저장됩니다. 따라서 Cloud Spanner는 로컬에서 기본 키로 결합을 수행하여 디스크 액세스와 네트워크 트래픽을 최소화할 수 있습니다. 다음 예시에서는 SingersAlbums가 기본 키인 SingerId로 조인됩니다.

SELECT s.FirstName, a.AlbumTitle
FROM Singers AS s JOIN Albums AS a ON s.SingerId = a.SingerId;

Cloud Spanner에서 테이블을 인터리브 처리하는 것이 필수는 아니지만 긴밀한 데이터 지역성 관계를 가진 테이블의 경우에는 권장됩니다. 하나의 행과 그 종속 항목의 크기가 몇 GB 이상이 될 가능성이 있다면 테이블을 인터리브 처리하지 마세요.

키 열

테이블의 키는 바뀔 수 없습니다. 즉, 기존 테이블에 키 열을 추가하거나 기존 테이블에서 키 열을 삭제할 수 없습니다.

NULL 저장

기본 키 열이 NULL을 저장하도록 정의할 수 있습니다. 기본 키 열에 NULL을 저장하려면 스키마의 해당 열에서 NOT NULL 절을 생략합니다.

다음은 기본 키 열 SingerId에서 NOT NULL 절을 생략하는 예시입니다. SingerId가 기본 키이기 때문에 Singers 테이블에서 해당 열에 NULL을 저장하는 행은 1개 이하여야 합니다.

CREATE TABLE Singers (
  SingerId   INT64,
  FirstName  STRING(1024),
  LastName   STRING(1024),
) PRIMARY KEY (SingerId);

기본 키 열의 null 사용 가능 속성은 상위 테이블과 하위 테이블 선언 간에 일치해야 합니다. 이 예시에서 Albums.SingerId INT64 NOT NULL은 허용되지 않습니다. Singers.SingerId가 생략하기 때문에 키 선언에서 NOT NULL 절을 생략해야 합니다.

CREATE TABLE Singers (
  SingerId   INT64,
  FirstName  STRING(1024),
  LastName   STRING(1024),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,  -- NOT ALLOWED!
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

허용되지 않는 유형

다음은 ARRAY 유형을 가질 수 없습니다.

  • 테이블의 키 열.
  • 색인의 키 열.

다중 테넌트 지원을 위한 설계

여러 고객에게 속한 데이터를 저장할 경우 다중 테넌트 지원 기능을 제공하는 것이 좋습니다. 예를 들어, 음악 서비스의 경우 각각의 레코드 라벨을 개별적으로 저장하는 것이 좋습니다.

기본 다중 테넌트 지원

멀티테넌시 지원을 설계하는 기본적인 방법은 고객별로 데이터베이스를 따로 만드는 것입니다. 이 예시에는 데이터베이스마다 고유한 Singers 테이블이 있습니다.

데이터베이스 1: Ackworth Records
SingerId FirstName LastName
1MarcRichards
2CatalinaSmith
데이터베이스 2: Cama Records
SingerId FirstName LastName
3MarcRichards
4GabrielWright
데이터베이스 3: Eagan Records
SingerId FirstName LastName
1BenjaminMartinez
2HannahHarris

Cloud Spanner에서 멀티테넌시 지원을 설계할 때 권장되는 방법은 고객별로 서로 다른 기본 키 값을 사용하는 것입니다. 테이블에 CustomerId 키 열 또는 이와 유사한 키 열을 포함합니다. CustomerId를 첫 번째 키 열로 만들면 각 고객의 데이터 지역성이 양호해집니다. Cloud Spanner가 크기와 부하 패턴에 따라 데이터를 여러 노드에 자동으로 분할합니다. 이 예시에는 고객별로 Singers 테이블이 하나씩 있습니다.

Cloud Spanner 멀티테넌시 데이터베이스
CustomerId SingerId FirstName LastName
11MarcRichards
12CatalinaSmith
23MarcRichards
24GabrielWright
31BenjaminMartinez
32HannahHarris

테넌트마다 별도의 데이터베이스가 있어야 하는 경우, 다음과 같은 제약에 유의해야 합니다.

  • 인스턴스당 데이터베이스 수와 데이터베이스당 테이블 수에 대한 제한이 있습니다. 고객 수에 따라 별도의 데이터베이스나 테이블을 갖는 것이 불가능할 수 있습니다.
  • 새 테이블과 인터리브 처리되지 않은 색인을 추가하려면 시간이 오래 걸릴 수 있습니다. 스키마가 새 테이블과 색인의 추가에 의존하도록 설계되어 있다면 원하는 성능을 얻지 못할 수도 있습니다.

별도의 데이터베이스를 만들려면 각 데이터베이스의 주당 스키마의 변동 횟수가 적도록 데이터베이스에 테이블을 분산한다면 더 성공적인 결과를 얻을 수 있습니다.

애플리케이션의 고객별로 테이블과 색인을 만들 경우, 모든 테이블과 색인을 동일한 데이터베이스에 넣지 마세요. 그 대신, 여러 데이터베이스에 분할하여 다수의 색인을 만들어 성능 문제를 완화하세요. 데이터베이스당 테이블 수와 색인 수에도 제한이 있습니다.