All Products
Search
Document Center

Object Storage Service:Pengambilan vektor skala besar dengan arsitektur multi-indeks

Last Updated:Jun 25, 2026

Seiring meningkatnya permintaan terhadap RAG dan pencarian semantik, sistem pengambilan vektor sering menghadapi dua tantangan umum:

  • Isolasi multi-tenant: Penyedia SaaS yang melayani basis pengetahuan untuk banyak pelanggan enterprise, atau perusahaan dengan basis pengetahuan terpisah untuk departemen berbeda, memerlukan isolasi data yang ketat.

  • Data skala ultra-besar: Ketika satu indeks berisi puluhan hingga ratusan juta vektor, latensi pengambilan meningkat secara signifikan sehingga sulit memenuhi persyaratan real-time.

OSS Vectors memungkinkan Anda membuat sejumlah besar indeks vektor dalam akun dan Wilayah yang sama. Dengan menggunakan arsitektur multi-indeks, Anda dapat mempartisi data berdasarkan tenant atau dimensi bisnis untuk mencapai isolasi data sekaligus pengambilan berkinerja tinggi.

image.png

Keunggulan arsitektur multi-indeks

  • Isolasi data: Data untuk tenant atau unit bisnis berbeda disimpan dalam indeks terpisah, sehingga mencegah kebocoran data lintas tenant.

  • Pengambilan lebih cepat: Mempartisi satu indeks besar menjadi beberapa indeks kecil mempersempit cakupan setiap pencarian. Dengan mencari beberapa indeks secara paralel lalu menggabungkan hasilnya, Anda dapat secara signifikan mengurangi waktu respons keseluruhan.

  • Operasi fleksibel: Konfigurasikan dimensi, model, dan algoritma kemiripan secara independen untuk setiap indeks. Untuk menghapus data tenant tertentu, cukup hapus indeks yang sesuai alih-alih memfilter dan menghapus catatan satu per satu.

Impor data berdasarkan tenant menggunakan CLI

Tool CLI oss-vectors-embed memungkinkan Anda menulis file ke indeks tertentu, sehingga memungkinkan impor data yang ditargetkan berdasarkan tenant atau dimensi bisnis.

Untuk instruksi instalasi, lihat Gunakan tool CLI OSS Vectors Embed untuk menulis dan mengkueri data vektor.

Sebelum memulai, pastikan Anda telah memenuhi persyaratan berikut:

  • Variabel lingkungan OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, dan DASHSCOPE_API_KEY telah dikonfigurasi.

  • Anda telah membuat bucket vektor dan indeks vektor yang sesuai untuk setiap tenant.

Ganti placeholder pada contoh berikut dengan nilai aktual Anda:

Placeholder

Deskripsi

<your-account-id>

ID akun Alibaba Cloud Anda

<your-vector-bucket>

Nama bucket vektor Anda

Tulis data ke indeks berbeda berdasarkan tenant

Tulis data untuk tenant berbeda ke indeks masing-masing guna memastikan isolasi data.

# Tulis dokumen untuk Tenant A ke indeks Tenant A
oss-vectors-embed \
  --account-id "<your-account-id>" \
  --vectors-region cn-hangzhou \
  put \
  --vector-bucket-name "<your-vector-bucket>" \
  --index-name "tenantcompanya" \
  --model-id text-embedding-v4 \
  --text-value "Knowledge base content for Tenant A" \
  --key "doc_001" \
  --metadata '{"tenant": "company_a", "category": "faq"}'

# Tulis dokumen untuk Tenant B ke indeks Tenant B
oss-vectors-embed \
  --account-id "<your-account-id>" \
  --vectors-region cn-hangzhou \
  put \
  --vector-bucket-name "<your-vector-bucket>" \
  --index-name "tenantcompanyb" \
  --model-id text-embedding-v4 \
  --text-value "Knowledge base content for Tenant B" \
  --key "doc_001" \
  --metadata '{"tenant": "company_b", "category": "manual"}'

Pencarian yang ditargetkan berdasarkan tenant

Mengkueri hanya indeks tenant target memastikan isolasi data.

# Cari hanya di indeks Tenant A
oss-vectors-embed \
  --account-id "<your-account-id>" \
  --vectors-region cn-hangzhou \
  query \
  --vector-bucket-name "<your-vector-bucket>" \
  --index-name "tenantcompanya" \
  --model-id text-embedding-v4 \
  --text-value "frequently asked questions" \
  --top-k 5 \
  --return-metadata

Bangun arsitektur multi-indeks dengan SDK

Python SDK

Sebelum memulai, instal SDK alibabacloud-oss-v2:

pip install alibabacloud-oss-v2

Pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.

Buat indeks multi-tenant

Beri nama indeks dengan ID tenant sebagai sufiks untuk membuat indeks vektor khusus secara batch.

import alibabacloud_oss_v2 as oss
import alibabacloud_oss_v2.vectors as oss_vectors

ACCOUNT_ID = "<your-account-id>"
REGION = "cn-hangzhou"
BUCKET = "<your-vector-bucket>"


def create_vector_client():
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = REGION
    cfg.account_id = ACCOUNT_ID
    return oss_vectors.Client(cfg)


client = create_vector_client()

# Buat indeks untuk tenant secara batch
tenant_ids = ["companya", "companyb", "companyc"]

for tenant_id in tenant_ids:
    index_name = f"tenant{tenant_id}"
    result = client.put_vector_index(oss_vectors.models.PutVectorIndexRequest(
        bucket=BUCKET,
        index_name=index_name,
        dimension=1024,
        data_type="float32",
        distance_metric="cosine",
    ))
    print(f"Index {index_name} created, status_code={result.status_code}")

Output:

Index tenantcompanya created, status_code=200
Index tenantcompanyb created, status_code=200
Index tenantcompanyc created, status_code=200

Tulis data berdasarkan tenant

Tulis data untuk tenant berbeda ke indeks masing-masing.

import alibabacloud_oss_v2 as oss
import alibabacloud_oss_v2.vectors as oss_vectors

ACCOUNT_ID = "<your-account-id>"
REGION = "cn-hangzhou"
BUCKET = "<your-vector-bucket>"


def create_vector_client():
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = REGION
    cfg.account_id = ACCOUNT_ID
    return oss_vectors.Client(cfg)


client = create_vector_client()

# Tulis data ke indeks Tenant A
result = client.put_vectors(oss_vectors.models.PutVectorsRequest(
    bucket=BUCKET,
    index_name="tenantcompanya",
    vectors=[
        {
            "key": "faq_001",
            "data": {"float32": [0.1] * 1024},  # Dimensi vektor harus sesuai dengan indeks.
            "metadata": {"tenant": "company_a", "category": "faq"}
        }
    ]
))
print(f"Tenant A write completed, status_code={result.status_code}")

# Tulis data ke indeks Tenant B
result = client.put_vectors(oss_vectors.models.PutVectorsRequest(
    bucket=BUCKET,
    index_name="tenantcompanyb",
    vectors=[
        {
            "key": "manual_001",
            "data": {"float32": [0.2] * 1024},  # Dimensi vektor harus sesuai dengan indeks.
            "metadata": {"tenant": "company_b", "category": "manual"}
        }
    ]
))
print(f"Tenant B write completed, status_code={result.status_code}")

Output:

Tenant A write completed, status_code=200
Tenant B write completed, status_code=200

Pencarian paralel dan penggabungan

Setelah mempartisi satu indeks besar menjadi beberapa indeks kecil, Anda dapat mengurangi waktu respons keseluruhan dengan mencari indeks secara paralel lalu menggabungkan dan mengurutkan hasilnya.

from concurrent.futures import ThreadPoolExecutor, as_completed

import alibabacloud_oss_v2 as oss
import alibabacloud_oss_v2.vectors as oss_vectors

ACCOUNT_ID = "<your-account-id>"
REGION = "cn-hangzhou"
BUCKET = "<your-vector-bucket>"


def create_vector_client():
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = REGION
    cfg.account_id = ACCOUNT_ID
    return oss_vectors.Client(cfg)


def search_index(client, index_name, query_vector, top_k=10):
    """Cari satu indeks."""
    result = client.query_vectors(oss_vectors.models.QueryVectorsRequest(
        bucket=BUCKET,
        index_name=index_name,
        query_vector=query_vector,
        return_metadata=True,
        return_distance=True,
        top_k=top_k,
    ))
    return {
        "index": index_name,
        "status_code": result.status_code,

        "vectors": result.vectors or [ ],

    }


def parallel_search(index_names, query_vector, top_k=10):
    """Cari beberapa indeks secara paralel dan gabungkan hasilnya."""
    client = create_vector_client()

    all_vectors = [ ]


    with ThreadPoolExecutor(max_workers=len(index_names)) as executor:
        futures = {
            executor.submit(search_index, client, idx, query_vector, top_k): idx
            for idx in index_names
        }
        for future in as_completed(futures):
            result = future.result()
            print(f"Index {result['index']} returned {len(result['vectors'])} results")
            all_vectors.extend(result["vectors"])

    # Urutkan berdasarkan jarak secara ascending (jarak lebih kecil berarti kemiripan lebih tinggi) dan ambil hasil top-K global.
    all_vectors.sort(key=lambda v: v.get("distance", float("inf")))
    return all_vectors[:top_k]


# Cari tiga indeks terpartisi secara paralel.
indices = ["tenantcompanya", "tenantcompanyb", "tenantcompanyc"]
query_vec = {"float32": [0.1] * 1024}  # Dimensi vektor harus sesuai dengan indeks.

results = parallel_search(indices, query_vec, top_k=5)
print(f"\nGlobal Top-5 after merging:")
for v in results:
    print(f"  key={v.get('key')}, distance={v.get('distance')}, metadata={v.get('metadata')}")

Output:

Index tenantcompanya returned 1 result
Index tenantcompanyb returned 1 result
Index tenantcompanyc returned 0 results

Global Top-5 after merging:
  key=faq_001, distance=0.0, metadata={'tenant': 'company_a', 'category': 'faq'}
  key=manual_001, distance=0.19999998807907104, metadata={'tenant': 'company_b', 'category': 'manual'}
Catatan: Setelah pencarian paralel di beberapa indeks, hasilnya digabungkan dan diurutkan di sisi client berdasarkan jarak. Untuk presisi lebih tinggi, Anda dapat menggunakan model Rerank untuk penyusunan ulang sekunder.

Go SDK

Sebelum memulai, instal SDK alibabacloud-oss-go-sdk-v2:

go get github.com/aliyun/alibabacloud-oss-go-sdk-v2

Pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.

Buat indeks multi-tenant

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/vectors"
)

const (
	region     = "cn-hangzhou"
	bucketName = "<your-vector-bucket>"
	accountId  = "<your-account-id>"
)

func main() {
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region).
		WithAccountId(accountId)

	client := vectors.NewVectorsClient(cfg)

	// Buat indeks untuk tenant secara batch.
	tenantIDs := [ ]string{"companya", "companyb", "companyc"}


	for _, tenantID := range tenantIDs {
		indexName := fmt.Sprintf("tenant%s", tenantID)
		result, err := client.PutVectorIndex(context.TODO(), &vectors.PutVectorIndexRequest{
			Bucket:         oss.Ptr(bucketName),
			IndexName:      oss.Ptr(indexName),
			Dimension:      oss.Ptr(1024),
			DataType:       oss.Ptr("float32"),
			DistanceMetric: oss.Ptr("cosine"),
		})
		if err != nil {
			log.Printf("Index %s creation failed: %v", indexName, err)
			continue
		}
		fmt.Printf("Index %s created, status_code=%d\n", indexName, result.StatusCode)
	}
}

Output:

Index tenantcompanya created, status_code=200
Index tenantcompanyb created, status_code=200
Index tenantcompanyc created, status_code=200

Pencarian paralel dan penggabungan

package main

import (
	"context"
	"fmt"
	"log"
	"sort"
	"sync"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/vectors"
)

const (
	region     = "cn-hangzhou"
	bucketName = "<your-vector-bucket>"
	accountId  = "<your-account-id>"
	dimension  = 1024
)


func makeVector(val float32, dim int) [ ]float32 {


	v := make([ ]float32, dim)

	for i := range v {
		v[i] = val
	}
	return v
}

func main() {
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region).
		WithAccountId(accountId)

	client := vectors.NewVectorsClient(cfg)


	indices := [ ]string{"tenantcompanya", "tenantcompanyb", "tenantcompanyc"}

	queryVector := map[string]any{"float32": makeVector(0.1, dimension)}

	var mu sync.Mutex

	var allVectors [ ]map[string]any

	var wg sync.WaitGroup

	for _, indexName := range indices {
		wg.Add(1)
		go func(idx string) {
			defer wg.Done()

			result, err := client.QueryVectors(context.TODO(), &vectors.QueryVectorsRequest{
				Bucket:         oss.Ptr(bucketName),
				IndexName:      oss.Ptr(idx),
				QueryVector:    queryVector,
				ReturnMetadata: oss.Ptr(true),
				ReturnDistance:  oss.Ptr(true),
				TopK:           oss.Ptr(10),
			})
			if err != nil {
				log.Printf("Index %s query failed: %v", idx, err)
				return
			}
			fmt.Printf("Index %s returned %d results\n", idx, len(result.Vectors))

			mu.Lock()
			allVectors = append(allVectors, result.Vectors...)
			mu.Unlock()
		}(indexName)
	}

	wg.Wait()

	// Urutkan berdasarkan jarak secara ascending dan ambil hasil top-K global.
	sort.Slice(allVectors, func(i, j int) bool {
		di, _ := allVectors[i]["distance"].(float64)
		dj, _ := allVectors[j]["distance"].(float64)
		return di < dj
	})

	topK := 5
	if len(allVectors) < topK {
		topK = len(allVectors)
	}

	fmt.Printf("\nGlobal Top-%d after merging:\n", topK)
	for _, v := range allVectors[:topK] {
		fmt.Printf("  key=%v, distance=%v, metadata=%v\n", v["key"], v["distance"], v["metadata"])
	}
}

Output:

Index tenantcompanya returned 1 result
Index tenantcompanyc returned 0 results
Index tenantcompanyb returned 1 result

Global Top-2 after merging:
  key=faq_001, distance=0, metadata=map[category:faq tenant:company_a]
  key=manual_001, distance=0.19999998807907104, metadata=map[category:manual tenant:company_b]

Praktik terbaik

  • Konvensi penamaan indeks: Gunakan ID tenant atau dimensi bisnis sebagai sufiks nama indeks, seperti tenant{tenantid}. Nama indeks hanya boleh berisi huruf kecil dan angka; karakter garis bawah dan tanda hubung tidak didukung.

  • Saat Anda memiliki jumlah tenant yang besar: Gunakan nama indeks untuk isolasi logis. Membuat indeks vektor OSS hanya memerlukan beberapa detik dan memiliki overhead manajemen minimal.

  • Saat Anda memerlukan latensi sangat rendah: Jika satu indeks tumbuh melebihi puluhan juta vektor, gunakan partisi horizontal berdasarkan logika bisnis, seperti waktu atau kategori. Kemudian, jalankan pencarian paralel di beberapa indeks dan gabungkan hasilnya.

  • Penyusunan ulang hasil (Rerank): Setelah menggabungkan hasil pencarian dari beberapa indeks, Anda dapat mengurutkan ulang hasil berdasarkan jarak atau menggunakan model Rerank untuk penyusunan ulang sekunder.

  • Pembersihan indeks: Untuk menghapus data tenant atau bisnis tertentu, panggil DeleteVectorIndex untuk menghapus indeks yang sesuai alih-alih memfilter dan menghapus data satu per satu.