Partial sync
필요한 것만 동기화하는 부분 동기화(partial sync) 기능이에요. 데이터베이스 페이지를 필요할 때마다(lazily) 가져와서 콜드 스타트를 빠르게 하고 대역폭을 줄여 줘요.
출처: 문서
본문
이 사용법은 로컬 Turso 데이터베이스를 동기화하기 위해 Turso Cloud를 사용하며, 계정이 있다고 가정해요.부분 동기화를 쓰면 파일 전체를 내려받지 않고도 애플리케이션이 데이터베이스를 열고 사용할 수 있어요. 클라이언트는 쿼리가 로컬에 없는 데이터를 만졌을 때, 그 시점에 Turso Cloud에서 데이터베이스 파일의 페이지를 가져와요(lazily fetch). 덕분에 큰 데이터베이스에서 시작 시간과 네트워크 사용량이 줄어들면서도, Turso의 표준 sync 솔루션이 사용하는 push/pull 메서드와 완전히 호환돼요.
Modes
연결 시점에 로컬에 무엇이 준비될지는 두 가지 부트스트랩 전략으로 정해져요.
- Prefix bootstrap: 데이터베이스 파일의 첫 N바이트를 내려받아요.
- 최소한의, 예측 가능한 시작 풋프린트를 원할 때 좋은 기본 선택이에요.
- Query bootstrap: 서버 쪽 SQL 쿼리를 실행해서 그 쿼리가 만지는 페이지들을 내려받아요.
- 좁은 작업 집합(예: 특정 사용자의 행, 메타데이터나 참조가 담긴 작은 테이블)만 채워 넣고 싶을 때 이상적이에요.
두 모드 모두 이후에도 없는 페이지를 필요할 때 계속 가져와요.
Prefix bootstrap
```ts TypeScript import { connect } from '@tursodatabase/sync';const db = await connect({ path: './app.db', url: 'turso://...', authToken: process.env.TURSO_AUTH_TOKEN, partialSyncExperimental: { bootstrapStrategy: { kind: 'prefix', length: 128 * 1024 }, // 128 KiB }, });
```py Python
import os
import turso.sync
conn = turso.sync.connect(
path="./app.db",
remote_url="turso://...",
auth_token=os.environ["TURSO_AUTH_TOKEN"],
partial_sync_experimental=turso.sync.PartialSyncOpts(
bootstrap_strategy=turso.sync.PartialSyncPrefixBootstrap(length=128 * 1024),
),
)
import (
\tturso "turso.tech/database/tursogo"
)
db, err := turso.NewTursoSyncDb(context.Background(), turso.TursoSyncDbConfig{
Path: "./app.db",
RemoteUrl: "turso://...",
AuthToken: os.Getenv("TURSO_AUTH_TOKEN"),
PartialSyncExperimental: turso.TursoPartialSyncConfig{
BootstrapStrategyPrefix: 128 * 1024, // 128 KiB
},
})
Query bootstrap
```ts TypeScript import { connect } from '@tursodatabase/sync';const db = await connect({
path: './app.db',
url: 'turso://...',
authToken: process.env.TURSO_AUTH_TOKEN,
partialSyncExperimental: {
bootstrapStrategy: {
kind: 'query',
query: SELECT * FROM messages WHERE user_id = 'u_123' LIMIT 100,
},
},
});
```py Python
import turso.sync
conn = turso.sync.connect(
path=":memory:",
remote_url="turso://...",
partial_sync_experimental=turso.sync.PartialSyncOpts(
bootstrap_strategy=turso.sync.PartialSyncQueryBootstrap(
query="SELECT * FROM messages WHERE user_id = 'u_123' LIMIT 100"
),
),
)
import (
\tturso "turso.tech/database/tursogo"
)
db, err := turso.NewTursoSyncDb(context.Background(), turso.TursoSyncDbConfig{
Path: "./app.db",
RemoteUrl: "turso://...",
AuthToken: os.Getenv("TURSO_AUTH_TOKEN"),
PartialSyncExperimental: turso.TursoPartialSyncConfig{
BootstrapStrategyQuery: "SELECT * FROM messages WHERE user_id = 'u_123' LIMIT 100",
},
})
Optimizations
Segment size (batched lazy reads)
원본 문서에는 인터랙티브 시각화가 있어요. 페이지 12개 중 3개가 캐시된 상태에서 페이지 7을 읽으면 세그먼트 5-8(새 페이지 3개)을 한 번에 가져오는 모습을 보여 줘요. — "Read page 7 → fetch segment 5-8 (3 new pages)"
클라이언트가 로컬에 없는 페이지가 필요하면 부분 동기화는 원격 데이터베이스에서 온디맨드로 가져와요.
왕복 횟수를 줄이고 가져오기를 빠르게 하려면 **세그먼트 크기(segment size)**를 설정할 수 있어요. 페이지 하나만 요청하는 대신, 클라이언트가 요청 한 번으로 페이지의 세그먼트 전체를 내려받는 방식이에요.
덕분에 네트워크 오버헤드를 분산(amortize)하고 곧 접근할 가능성이 높은 근처 페이지들을 미리 채워 넣을 수 있어요.
How it works
데이터베이스가 다음과 같다고 해 볼게요.
page_size = 4 KiBsegment_size = 16 KiB
로컬 쿼리가 페이지 6을 만지면 클라이언트는 그 페이지가 속한 세그먼트를 계산해요.
- 16 KiB 세그먼트 = 4개 페이지
- 페이지 6을 덮는 세그먼트 = 페이지 5-8
그러면 클라이언트는 네 페이지 전부를 요청 한 번으로 가져와 로컬에 저장해요. 그 페이지들을 다시 읽을 때는 추가 네트워크 비용이 들지 않아요.
Benefits
- HTTP 요청 수 감소 (페이지 하나씩 여러 번 대신 세그먼트 한 번)
- 자주 쓰는 범위(hot range)를 더 빠르게 채워 넣기
- 공간적 지역성(spatial locality)이 있는 워크로드(예: 범위 스캔, 인덱스 조회)에서 더 나은 성능
Default
기본 segment_size는 128 KiB(4 KiB 페이지 크기 기준 보통 32개 페이지)예요. 요청 오버헤드와 전송 총 바이트 사이에서 좋은 균형을 제공해요.
반대로 아주 드문드문한/무작위 접근 워크로드라면 세그먼트 크기를 줄이는 편이 유리할 수 있어요.
```ts TypeScript await connect({ ... partialSyncExperimental: { bootstrapStrategy: { kind: 'prefix', length: 128 * 1024 }, // 128 KiB segmentSize: 16 * 1024, }, }); ```turso.sync.connect(
...
partial_sync_experimental=turso.sync.PartialSyncOpts(
bootstrap_strategy=turso.sync.PartialSyncPrefixBootstrap(length=128 * 1024),
segment_size=16 * 1024,
),
)
turso.NewTursoSyncDb(context.Background(), turso.TursoSyncDbConfig{
...
PartialSyncExperimental: turso.TursoPartialSyncConfig{
BootstrapStrategyPrefix: 128 * 1024, // 128 KiB
SegmentSize: 16 * 1024,
},
})
Prefetch
원본 문서에는 인터랙티브 시각화가 있어요. 페이지 4를 읽으면 내부 B-트리 노드가 참조하는 자식 페이지 2개(11, 12)를 미리 내려받는 모습을 보여 줘요. — "Read page 4 → prefetch 2 child pages (11, 12)"
Prefetch는 지연 페이지 가져오기 위에 얹는 선택적 최적화예요. 켜 두면 클라이언트가 현재 쿼리에 필요한 페이지만 가져오는 게 아니라, 새로 내려받은 페이지의 구조와 최근 접근 패턴을 살펴서 다음에 필요할 가능성이 높은 페이지를 예측해요.
클라이언트가 접근 패턴의 자연스러운 연속(예: 내부 B-트리 노드가 참조하는 자식 페이지)을 감지하면 그 페이지들을 미리 다운로드해요. 이후의 온디맨드 가져오기 횟수를 줄여 주고, 범위 스캔·인덱스 순회·순차 조회 같은 연산 중 멈춤(stall)을 피하는 데 도움이 돼요.
```ts TypeScript await connect({ ... partialSyncExperimental: { bootstrapStrategy: { kind: 'prefix', length: 128 * 1024 }, // 128 KiB prefetch: true, }, }); ```turso.sync.connect(
...
partial_sync_experimental=turso.sync.PartialSyncOpts(
bootstrap_strategy=turso.sync.PartialSyncPrefixBootstrap(length=128 * 1024),
prefetch=True,
),
)
turso.NewTursoSyncDb(context.Background(), turso.TursoSyncDbConfig{
...
PartialSyncExperimental: turso.TursoPartialSyncConfig{
BootstrapStrategyPrefix: 128 * 1024, // 128 KiB
Prefetch: true,
},
})
`segment_size`와 `prefetch`는 서로 보완적이에요.
세그먼트 크기는 가까운 페이지들을 한 번의 온디맨드 가져오기로 묶어 주고, prefetch는 쿼리의 접근 패턴을 보고 다음에 필요할 가능성이 높은 추가 페이지를 미리 가져와요.
둘을 함께 쓰면 실제 워크로드에서 가장 좋은 성능을 낼 수 있어요.
더 알아보기 (Learn more)
- Usage - 동기화 연산 사용법
- Checkpoint - 로컬 WAL 압축
- Conflict Resolution - 동기화 충돌 해결
- Local Sync Server - 로컬 동기화 서버