이 SQL과 NoSQL 비교는 SQL Server 데이터베이스를 Couchbase로 변환한 후 다음 단계입니다. In 이전 게시물를 사용하여 SQL Server에서 Couchbase로 AdventureWorks를 복사했습니다.
이 글에서는 SQL Server를 사용하는 ASP.NET Core 애플리케이션과 동일한 애플리케이션이 Couchbase를 사용하는 방법을 보여드리겠습니다. 따라 해보고 싶으시다면 SqlServerToCouchbase 프로젝트 에서 확인하세요.
이전 게시물과 달리 애플리케이션의 "자동" 변환을 시도하지 않습니다. 대신 애플리케이션 수준에서 SQL과 NoSQL을 비교하는 것으로 생각하시면 됩니다.
ASP.NET SQL Server 애플리케이션
아주 간단한 ASP.NET Core REST API 스타일의 애플리케이션을 만들었습니다. 저는 엔티티 프레임워크를 사용했지만 Dapper, ADO.NET, NHibernate 등을 사용하시는 분들도 쉽게 따라할 수 있을 것입니다.
각 엔드포인트는 JSON을 반환합니다. 또한 프로젝트에 Swashbuckle을 추가하여 브라우저에서 OpenAPI를 통해 바로 요청을 발행할 수 있도록 했습니다.
ASP.NET 카우치베이스 서버 애플리케이션
카우치베이스 버전의 애플리케이션은 동일한 SQL Server AdventureWorks 데이터를 사용하기 때문에 동일한 데이터를 반환합니다.
애플리케이션에서 저는 카우치베이스 .NET SDK 그리고 카우치베이스 거래 라이브러리. (다음을 사용할 수 있습니다. Linq2Couchbase 엔티티 프레임워크 대체의 한 유형으로).
그렇지 않으면 애플리케이션은 동일하며 SQL과 NoSQL 비교(및 대조)를 제공합니다. 엔드포인트는 JSON을 반환하고 Swashbuckle이 설치되어 있습니다.
각 샘플에는 컨트롤러가 하나씩 있습니다. 컨트롤러의 각 엔드포인트를 살펴보고 SQL과 NoSQL 비교를 수행해 보겠습니다.
SQL과 NoSQL 비교: ID로 가져오기
먼저 GetPersonByIdAsync
엔드포인트입니다. 개인 ID가 주어지면 이 엔드포인트는 주어진 ID에 대한 개인 데이터를 반환합니다.
SQL Server
다음은 엔티티 프레임워크를 사용하는 SQL Server 예제입니다:
1 2 3 4 5 6 7 8 |
[HttpGet("/person/{personId}")] public 비동기 작업<IActionResult> GetPersonByIdAsync(int personId) { var 사람 = 기다림 _context.사람 .단일 또는 기본 동기화(p => p.비즈니스 엔티티 ID == personId); 반환 확인(사람); } |
이 메서드의 다른 버전도 작성했습니다. GetPersonByIdRawAsync
는 "원시" SQL 쿼리를 사용합니다. 이 쿼리는 엔티티 프레임워크(위)가 궁극적으로 생성하는 쿼리와 매우 유사하며, Dapper 접근 방식과도 유사합니다.
1 2 3 4 5 6 7 8 9 |
[HttpGet("/personRaw/{personId}")] public 비동기 작업<IActionResult> GetPersonByIdRawAsync(int personId) { var 사람 = 기다림 _context.사람 .FromSqlRaw(@"SELECT * FROM Person.Person WHERE BusinessEntityID = {0}", personId) .단일 또는 기본 동기화(); 반환 확인(사람); } |
어느 쪽이든 SQL 쿼리가 실행되고 있다는 점에 유의하세요.
N1QL을 사용하면 매우 유사한 방식으로 Couchbase의 데이터를 쿼리할 수 있습니다. 다음은 GetPersonByIdRawAsync
를 사용하세요:
1 2 3 4 5 6 7 8 9 10 |
[HttpGet("/personRaw/{personId}")] public 비동기 작업<IActionResult> GetPersonByIdRawAsync(int personId) { var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 클러스터 = 버킷.클러스터; var personResult = 기다림 클러스터.QueryAsync<사람>(@" SELECT p.* FROM AdventureWorks2016.Person.Person p WHERE p.BusinessEntityID = $personId", new 쿼리 옵션().매개변수("personId", personId)); 반환 확인(기다림 personResult.행.단일 또는 기본 동기화()); } |
("버킷"에서 "클러스터"로 이동하는 추가 단계가 있습니다. 이 단계를 건너뛸 수도 있지만 저는 컨트롤러의 다른 곳에서 버킷을 사용하기 때문에 그대로 두었습니다.)
그러나 N1QL 쿼리를 사용하면 인덱싱, 쿼리 구문 분석 등 약간의 추가 오버헤드가 발생합니다. Couchbase를 사용하면 이미 개인 ID를 알고 있는 경우 N1QL 쿼리를 건너뛰고 직접 키/값(K/V) 조회를 수행할 수 있습니다.
K/V로 신분증 확인
키는 이미 알고 있으므로 인자로 주어집니다. SQL을 사용하는 대신 키/값 조회를 해보겠습니다. 저는 다음과 같은 엔드포인트 메서드에서 이 작업을 수행했습니다. GetPersonByIdAsync
:
1 2 3 4 5 6 7 8 9 |
[HttpGet("/person/{personId}")] public 비동기 작업<IActionResult> GetPersonByIdAsync(int personId) { var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 범위 = 기다림 버킷.ScopeAsync("사람"); var coll = 기다림 범위.CollectionAsync("사람"); var 사람 문서 = 기다림 coll.GetAsync(personId.ToString()); 반환 확인(사람 문서.ContentAs<사람>()); } |
SQL Server와 달리 Couchbase는 데이터와 상호 작용할 수 있는 다양한 API를 지원합니다. 이 경우 키/값 조회는 메모리에서 직접 Person 문서를 가져옵니다. SQL 쿼리를 파싱하거나 인덱싱을 사용할 필요가 없습니다. Couchbase의 키/값 조회는 종종 마이크로초 단위로 측정됩니다.
제 조언: 가능하면 키/값 조회를 사용하세요.
ID로 확장된 엔터티 가져오기
데이터는 복잡하고 여러 테이블에 걸쳐 있을 수 있습니다(또는 Couchbase의 경우 여러 문서에 걸쳐 있을 수 있습니다). 사용 중인 도구에 따라 관련 엔티티를 로드할 수 있는 일부 기능이 있을 수 있습니다.
예를 들어, 엔티티 프레임워크를 사용하면 포함
를 사용하여 다음과 같이 관련 엔티티를 가져옵니다. GetPersonByIdExpandedAsync
예제:
1 2 3 4 5 6 7 8 9 |
[HttpGet("/개인확장/{개인아이디}")] public 비동기 작업<IActionResult> GetPersonByIdExpandedAsync(int personId) { var 사람 = 기다림 _context.사람 .포함(p => p.이메일 주소) .단일 또는 기본 동기화(p => p.비즈니스 엔티티 ID == personId); 반환 확인(사람); } |
엔티티 프레임워크는 이 작업을 수행하기 위해 뒤에서 JOIN 및/또는 여러 SELECT 쿼리를 생성할 수 있습니다.
엔티티 프레임워크뿐만 아니라 모든 O/RM이 위험할 수 있는 부분입니다. SQL 프로파일러와 같은 도구를 사용하여 실제로 어떤 쿼리가 실행되고 있는지 확인해야 합니다.
참고
|
O/RM이 도움이 될 수 있지만 SQL에서 NoSQL로 와 비교할 때, 임피던스 불일치는 NoSQL 세계에서 훨씬 덜 문제가 된다는 점을 기억하는 것이 중요합니다. |
Couchbase 샘플의 경우, 엔티티 프레임워크를 사용하지 않고 대신에 NEST 구문 SQL 표준의 N1QL 확장의 일부입니다. 다음은 Couchbase 버전의 GetPersonByIdExpandedAsync
외모:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[HttpGet("/개인확장/{개인아이디}")] public 비동기 작업<IActionResult> GetPersonByIdExpandedAsync(int personId) { var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 클러스터 = 버킷.클러스터; var personResult = 기다림 클러스터.QueryAsync<사람>(@" SELECT p.*, EmailAddresses FROM AdventureWorks2016.Person.Person p NEST AdventureWorks2016.Person.EmailAddress 이메일 주소 ON 이메일 주소.비즈니스 엔티티 ID = p.비즈니스 엔티티 ID WHERE p.BusinessEntityID = $personId", new 쿼리 옵션().매개변수("personId", personId)); 반환 확인(기다림 personResult.행.단일 또는 기본 동기화()); } |
NEST는 조인된 데이터를 중첩된 JSON 객체에 넣는 일종의 JOIN입니다. O/RM을 사용하여 데이터를 매핑하는 대신 이 데이터를 C# 객체로 직접 직렬화할 수 있습니다.
페이징 쿼리
데이터를 조회할 수 있는 키가 하나도 없는 경우를 예로 들어보겠습니다. 결과의 '페이지'를 반환하는 메서드를 살펴보겠습니다(아마도 UI 그리드나 목록을 채우기 위한 것일 수 있습니다).
SQL Server의 페이징
SQL Server 버전은 다음과 같습니다. GetPersonsPageAsync
:
1 2 3 4 5 6 7 8 9 10 11 12 |
[HttpGet("/사람/페이지/{페이지 번호}")] public 비동기 작업<IActionResult> GetPersonsPageAsync(int 페이지 번호) { var 페이지 크기 = 10; var 사람 페이지 = 기다림 _context.사람 .주문 기준(p => p.성) .건너뛰기(페이지 번호 * 페이지 크기) .Take(페이지 크기) .선택(p => new { p.비즈니스 엔티티 ID, p.이름, p.성 }) .ToListAsync(); 반환 확인(사람 페이지); } |
엔티티 프레임워크 사용, 주문 기준
, 건너뛰기
및 Take
는 일반적으로 페이징에 사용됩니다. SQL Server 프로파일러를 열면 생성되는 SQL은 다음과 같습니다:
1 2 3 4 |
exec sp_실행 쿼리 N'SELECT [p].[BusinessEntityID], [p].[FirstName], [p].[LastName] FROM [사람].[사람] AS [p] [p].[성]으로 주문하기 오프셋 @__p_0 행 가져 오기 다음 @__p_0 행만',N'@__p_0 int',@__p_0=10 |
오프셋 ... 행 가져 오기 다음 ...
는 여기서 페이징에 사용되는 구문입니다.
Couchbase의 페이징
페이징 구문은 항상 SQL 구현에 따라 다릅니다. Couchbase는 이 점에서 Oracle/MySQL 구문에 더 의존합니다. 다음은 Couchbase 버전의 GetPersonsPageAsync
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[HttpGet("/사람/페이지/{페이지 번호}")] public 비동기 작업<IActionResult> GetPersonsPageAsync(int 페이지 번호) { var 페이지 크기 = 10; var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 버킷 이름 = 버킷.이름; var 클러스터 = 버킷.클러스터; var 사람 페이지 = 기다림 클러스터.QueryAsync<사람>($@" SELECT p.LastName, p.BusinessEntityID, p.FirstName FROM `{버킷 이름}`.Person.Person p p.LastName이 누락되지 않은 경우 p.성으로 주문 LIMIT {pageSize} OFFSET {(pageNum * pageSize)} "); 반환 확인(기다림 사람 페이지.행.ToListAsync()); } |
이 경우 제한 ... 오프셋 ...
가 사용 중입니다.
또한 p.LastName이 누락되지 않은 경우
. 카우치베이스는 NoSQL 데이터베이스이므로 쿼리 엔진은 다음을 가정할 수 없습니다. 성
를 포함한 모든 문서에 p.성으로 주문
. 이것을 추가하면 어디
절을 사용하면 쿼리는 이제 어떤 인덱스를 사용할지 알 수 있습니다. 이 절이 없으면 쿼리를 실행하는 데 훨씬 더 오래 걸립니다.
ACID 트랜잭션으로 업데이트
이 예제에서는 SQL Server와 Couchbase 모두에서 관계형 모델을 사용하므로 두 애플리케이션 모두에서 ACID 트랜잭션이 중요할 것입니다.
이 예제에서는 PersonUpdateApi
를 업데이트할 수 있습니다. 둘 다 사람의 이름과 이메일 주소입니다. 이 데이터는 두 개의 개별 테이블/행(SQL Server) 또는 두 개의 개별 문서(Couchbase)에 있으므로, 이 작업은 전부 아니면 전무의 원자 연산이 되기를 원합니다.
참고
|
한 사람이 여러 개의 이메일 주소를 가질 수 있지만 이 데이터 세트에서는 드물기 때문에 (API를 단순화하기 위해) 둘 다에 대해 ID를 지정합니다. |
엔티티 프레임워크가 포함된 ACID
다음은 엔티티 프레임워크를 사용하여 Person 테이블의 데이터 행과 EmailAddress 테이블의 데이터 행을 모두 업데이트하는 ACID 트랜잭션의 예입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
[HttpPut("/사람")] public 비동기 작업<IActionResult> 업데이트 구매 주문 동기화(PersonUpdateApi personUpdateApi) { var 트랜잭션 = 기다림 _context.데이터베이스.비동기 트랜잭션 시작(); 시도 { // 사람 찾기 var 사람 = 기다림 _context.사람 .포함(p => p.이메일 주소) .단일 또는 기본 동기화(p => p.비즈니스 엔티티 ID == personUpdateApi.PersonId); // 업데이트 이름 사람.이름 = personUpdateApi.이름; 사람.성 = personUpdateApi.성; // 특정 이메일 주소를 가져와 업데이트 // 제공된 ID가 유효하지 않으면 예외가 발생합니다. var 이메일 = 사람.이메일 주소.싱글(e => e.이메일주소ID == personUpdateApi.이메일 주소); 이메일.이메일 주소 = personUpdateApi.이메일 주소; 기다림 _context.SaveChangesAsync(); // 커밋 트랜잭션 기다림 트랜잭션.CommitAsync(); 반환 확인($"{personUpdateApi.PersonId} 사용자 이름 및 이메일이 업데이트되었습니다."); } catch (예외 ex) { 기다림 트랜잭션.롤백 비동기화(); 반환 BadRequest("문제가 발생하여 트랜잭션이 롤백되었습니다."); } } |
거래의 네 가지 주요 부분에 유의하세요:
- 거래 시작(
_context.Database.BeginTransactionAsync();
) 시도
/catch
- 트랜잭션 커밋(
트랜잭션.CommitAsync()를 기다립니다;
) - 롤백 트랜잭션의
catch
(트랜잭션.롤백비동기();
)
이것은 최근 몇 년 동안 SQL과 NoSQL을 비교하는 중요한 기능입니다. Couchbase를 사용하면 이제 ACID 트랜잭션이 가능합니다.
카우치베이스 트랜잭션이 있는 ACID
카우치베이스의 경우 API는 약간 다르지만 단계는 모두 동일합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[HttpPut("/사람")] public 비동기 작업<IActionResult> 업데이트 구매 주문 동기화(PersonUpdateApi personUpdateApi) { // 버킷, 클러스터 및 컬렉션 설정 var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 범위 = 기다림 버킷.ScopeAsync("사람"); var 사람콜 = 기다림 범위.CollectionAsync("사람"); var 이메일콜 = 기다림 범위.CollectionAsync("이메일 주소"); // 트랜잭션 생성 var 클러스터 = 버킷.클러스터; var 트랜잭션 = 거래.만들기(클러스터, 트랜잭션 컨피그 빌더.만들기() .내구성 수준(내구성 수준.없음) .빌드()); 시도 { 기다림 트랜잭션.RunAsync(비동기 (컨텍스트) => { // 사람 및 이메일 문서 업데이트 // API 객체에 전달된 값에 기반 var 사람키 = personUpdateApi.PersonId.ToString(); var 이메일 키 = 사람키 + "::" + personUpdateApi.이메일 주소.ToString(); var 사람 = 기다림 컨텍스트.GetAsync(사람콜, 사람키); var 이메일 = 기다림 컨텍스트.GetAsync(이메일콜, 이메일 키); var 사람 문서 = 사람.ContentAs<동적>(); var 이메일 문서 = 이메일.ContentAs<동적>(); 사람 문서.이름 = personUpdateApi.이름; 사람 문서.성 = personUpdateApi.성; 이메일 문서.이메일 주소 = personUpdateApi.이메일 주소; 기다림 컨텍스트.ReplaceAsync(사람, 사람 문서); 기다림 컨텍스트.ReplaceAsync(이메일, 이메일 문서); }); 반환 확인($"{personUpdateApi.PersonId} 사용자 이름 및 이메일이 업데이트되었습니다."); } catch (예외 ex) { 반환 BadRequest("문제가 발생하여 거래가 롤백되었습니다."); } } |
주요 단계는 동일합니다:
- 거래 시작(
트랜잭션.RunAsync( ... )
) 시도
/catch
- 트랜잭션 커밋(암시적이지만
context.CommitAsync()
사용 가능) - 롤백 트랜잭션(다시 한 번 암시되지만
context.RollbackAsync()
를 사용할 수 있습니다).
두 경우 모두 ACID 트랜잭션이 있습니다. 와 달리 그러나 SQL Server는 나중에 Couchbase의 데이터를 최적화하고 통합하여 필요한 ACID 트랜잭션의 양을 줄이고 성능을 향상시킵니다.
저장 프로시저: SQL과 NoSQL 비교
저장 프로시저는 때때로 논란의 여지가 있는 주제입니다. 일반적으로 저장 프로시저에는 많은 기능과 논리가 포함될 수 있습니다.
SQL Server의 저장 프로시저
"ListSubcomponents"라는 저장 프로시저를 만들었습니다 ( 깃허브에 대한 자세한 내용). 엔티티 프레임워크에서는 다음을 사용할 수 있습니다. FromSqlRaw
를 실행하고 그 결과를 C# 객체에 매핑합니다. 의사 엔티티 C# 객체를 다음과 같이 만들었습니다. 하위 컴포넌트 나열
이 스프로크에만 사용됩니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// sproc 예제 - 예제 저장 프로시저.sql 참조 [HttpGet("/getListSubcomponents/{list가격 최소값}/{list가격 최대값}")] public 비동기 작업<IActionResult> GetListSubcomponents(십진수 목록 가격 최소, 십진수 목록 가격 최대) { var 목록 가격 최소 매개변수 = new SqlParameter("@ListPriceMin", SqlDbType.십진수) {가치 = 목록 가격 최소 }; var 목록 가격 최대 매개변수 = new SqlParameter("@ListPriceMax", SqlDbType.십진수) {가치 = 목록 가격 최대 }; var 결과 = 기다림 _context.하위 컴포넌트 나열 .FromSqlRaw("EXECUTE dbo.ListSubcomponents @ListPriceMin, @ListPriceMax", 목록 가격 최소 매개변수, 목록 가격 최대 매개변수) .ToListAsync(); 반환 확인(결과); } |
저장 프로시저에는 두 개의 매개 변수가 있습니다.
카우치베이스 사용자 정의 기능
Couchbase에는 아직 "저장 프로시저"라는 것이 없지만, 필요한 경우 복잡한 로직을 포함할 수 있는 사용자 정의 함수(UDF)라는 것이 있습니다.
라는 UDF를 만들었습니다. 하위 컴포넌트 나열
(또한 깃허브에서 보기)의 기능과 일치하는 SQL Server 스프로크입니다.
ASP.NET에서 해당 UDF를 실행하는 방법은 다음과 같습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// sproc 예제 - 예제 저장 프로시저.sql 참조 [HttpGet("/getListSubcomponents/{list가격 최소값}/{list가격 최대값}")] public 비동기 작업<IActionResult> GetListSubcomponents(십진수 목록 가격 최소, 십진수 목록 가격 최대) { var 버킷 = 기다림 _버킷 공급자.GetBucketAsync(); var 클러스터 = 버킷.클러스터; var 옵션 = new 쿼리 옵션(); 옵션.매개변수("$listPriceMin", 목록 가격 최소); 옵션.매개변수("$listPriceMax", 목록 가격 최대); var 결과 = 기다림 클러스터.QueryAsync<목록 하위 컴포넌트>( "SELECT l.* FROM ListSubcomponents($listPriceMin, $listPriceMax) l", 옵션); 반환 확인(기다림 결과.행.ToListAsync()); } |
두 개의 매개 변수를 사용하여 Couchbase에서 이를 호출하는 것은 엔티티 프레임워크에서 FromSqlRaw를 사용하는 것과 매우 유사합니다.
성능 - SQL과 NoSQL 비교
이제 앱을 Couchbase를 사용하도록 변환했는데 새 버전이 적어도 이전 SQL Server 버전만큼 빠르게 실행되나요?
대답하기 복잡한 질문입니다:
- 데이터 모델을 최적화하지 않았습니다. 여전히 다음에서 데이터를 리터럴로 변환하는 방식을 사용하고 있습니다. 이전 게시물.
- 데이터 액세스는 사용 사례마다 매우 다양할 수 있습니다.
- 환경은 사람마다, 회사마다 크게 다를 수 있습니다.
하지만 저는 정신 상태를 점검하기 위해 '백 오브 더 엔벨로프' 부하 테스트를 해보고 싶었습니다.
로컬 컴퓨터에서 두 애플리케이션을 모두 실행했고, 다음을 사용했습니다. ngrok 를 사용하여 인터넷에 노출시켰습니다. 그런 다음 loader.io (동시성 부하 테스트를 위한 훌륭한 도구). 그런 다음 '페이징' 엔드포인트에 대해서만 몇 가지 간단한 성능 테스트를 실행했습니다. 이 엔드포인트는 제가 성능에 대해 가장 우려하는 엔드포인트이며, 엔드포인트 중에서 가장 "사과와 사과"를 비교한 SQL 및 NoSQL이라고 생각합니다.
로드 테스트 SQL과 NoSQL 비교
다음은 SQL Server 애플리케이션의 결과입니다:
다음은 카우치베이스 서버 애플리케이션의 결과입니다:
SQL 및 NoSQL 비교 부하 테스트 결과 해석하기
이것은 "Couchbase가 SQL Server보다 빠르다"는 벤치마크나 데이터 포인트가 아닙니다.
이는 단지 정신 상태를 점검하기 위한 것입니다.
부하가 걸린 상태에서 이전만큼 좋은 성능을 얻지 못한다면 뭔가 잘못하고 있는 것일 수 있습니다. 이는 개념 증명 프로세스. 카우치베이스, 특히 카우치베이스 7은 매우 관계형 친화적이지만, 여전히 다음과 같은 차이점과 뉘앙스가 있습니다. 모든 이 프로세스를 통해 여러분과 프로젝트에 가장 중요한 차이점을 파악할 수 있습니다.
보다 강력한 벤치마크를 찾고 계신다면 다음 리소스를 참고하세요:
- 알토로스의 벤치마크 보고서 (타사)
- 클라우드 벤치마크
- 카우치베이스 서버 "ShowFast" 벤치마크
결론
아주 기본적인 부하 테스트와 함께 애플리케이션 코드의 SQL과 NoSQL 비교 및 변환을 통해 제가 할 수 있다는 것을 알 수 있었습니다:
- 모델링 변경 없이 관계형 데이터 모델 그대로 호스팅
- Couchbase SDK를 사용하도록 ASP.NET 엔드포인트 변환하기
- 낮은 위험으로 확장 및 개선할 수 있는 충분한 여지가 있는 최소한의 성능으로 시작할 수 있을 것으로 기대합니다.
사용 사례는 다를 수 있지만, 이 전환 과정에서 Couchbase가 제공한 정보를 기억하세요:
부록
다음은 제가 애플리케이션에서 수행한 SQL과 NoSQL 비교에 대한 간결한 가이드입니다.
SQL Server 작업 | 카우치베이스 운영 |
---|---|
한 행/엔터티 읽기/쓰기 |
|
여러 행/페이지 읽기/쓰기 |
|
관련 엔티티가 있는 엔티티 하나를 선택합니다. |
N1QL 쿼리 NEST |
BeginTransaction |
|
저장 프로시저 |
미리 알림:
- 가능하면 키/값 API로 전환하세요.
- N1QL 작성 시 인덱싱, 인덱싱 계획 시각화 및 인덱스 어드바이저 사용
- 다음과 같은 경우에만 ACID 트랜잭션을 사용합니다.
- 성능 목표에 대해 생각하고 테스트 방법을 설정하세요.
다음 단계
확인 현재 베타 버전인 Couchbase Server 7를 지금 다운로드하세요. 무료로 다운로드할 수 있습니다. 관계형 데이터를 로드하고 몇 가지 엔드포인트를 변환하여 프로세스가 제대로 작동하는지 확인해 보세요.