Este tópico apresenta um benchmark de desempenho da extensão pgvector com índice HNSW em uma instância ApsaraDB RDS for PostgreSQL. O benchmark utiliza a ferramenta ann-benchmarks para avaliar o desempenho da implementação do RDS em comparação à versão da comunidade, considerando métricas essenciais como taxa de recall, consultas por segundo (QPS) e tempo de criação do índice.
Ambiente de teste
Para evitar imprecisões causadas por flutuações de rede, coloque sua instância RDS PostgreSQL e a instância ECS cliente na mesma Virtual Private Cloud (VPC) e no mesmo vSwitch.
|
Componente |
Descrição |
|
Instância RDS PostgreSQL |
|
|
Instância ECS |
|
|
Ferramenta de teste |
Importante
Por padrão, o ANN-Benchmarks testa o desempenho single-thread. Para testar o desempenho simultâneo da instância, consulte pgvector performance test (based on an IVF index). |
Pré-requisitos
Instância RDS for PostgreSQL
Crie uma conta com altos privilégios chamada
ann_testusere um banco de dados de teste chamadoann_testdb. Para mais informações, consulte Create accounts and databases.Instale o plugin pgvector (vector) no banco de dados
ann_testdb. Para mais informações, consulte Manage plugins.
Instância ECS cliente
Instale o Docker. Para mais informações, consulte Install Docker.
-
Execute os comandos a seguir para baixar a ferramenta ann-benchmarks.
cd ~ git clone https://github.com/erikbern/ann-benchmarks.git -
Execute os comandos abaixo para criar e ativar um ambiente virtual Python 3.10.6 chamado
ann_testusando Conda.yum install git yum install conda conda create -n ann_test python=3.10.6 conda init bash source /usr/etc/profile.d/conda.sh conda activate ann_test -
Execute os comandos a seguir para instalar as dependências do ann-benchmarks.
cd ~/ann-benchmarks/ pip install -r requirements.txt
Procedimento de teste
Todas as etapas deste procedimento são executadas no ambiente virtual ann_test. Se a sessão expirar ou for encerrada por qualquer motivo, use o comando conda activate ann_test para retornar ao ambiente.
Etapa 1: Configurar as definições de conexão
Edite o arquivo ~/ann-benchmarks/ann_benchmarks/algorithms/pgvector/module.py na ferramenta de benchmark para adicionar as configurações de conexão a seguir. Preencha os valores com base no seu ambiente real.
# Set the connection parameters for PostgreSQL
os.environ['ANN_BENCHMARKS_PG_USER'] = 'ann_testuser' # The user for the RDS PostgreSQL instance
os.environ['ANN_BENCHMARKS_PG_PASSWORD'] = 'testPawword' # The password for the RDS PostgreSQL user
os.environ['ANN_BENCHMARKS_PG_DBNAME'] = 'ann_testdb' # The database name of the RDS PostgreSQL instance
os.environ['ANN_BENCHMARKS_PG_HOST'] = 'pgm-****.pg.rds.aliyuncs.com' # The internal endpoint of the RDS PostgreSQL instance
os.environ['ANN_BENCHMARKS_PG_PORT'] = '5432' # The internal port number of the RDS PostgreSQL instance
os.environ['ANN_BENCHMARKS_PG_START_SERVICE'] = 'false' # Disable automatic service startup
Etapa 2: Configurar os parâmetros de teste do ann-benchmarks****
De acordo com seus requisitos de teste, edite o arquivo ~/ann-benchmarks/ann_benchmarks/algorithms/pgvector/config.yml na ferramenta de benchmark. Por exemplo:
float:
any:
- base_args: ['@metric']
constructor: PGVector
disabled: false
docker_tag: ann-benchmarks-pgvector
module: ann_benchmarks.algorithms.pgvector
name: pgvector
run_groups:
M-16(100):
arg_groups: [{M: 16, efConstruction: 100}]
args: {}
query_args: [[10, 20, 40, 80, 120, 200, 400, 800]]
M-16(200):
arg_groups: [{M: 16, efConstruction: 200}]
args: {}
query_args: [[10, 20, 40, 80, 120, 200, 400, 800]]
M-24(200):
arg_groups: [{M: 24, efConstruction: 200}]
args: {}
query_args: [[10, 20, 40, 80, 120, 200, 400, 800]]
Este teste divide-se em três grupos: M-16(100), M-16(200) e M-24(200). Cada grupo utiliza arg_groups para definir os parâmetros de criação do índice HNSW e query_args para configurar os parâmetros de recuperação.
|
Parâmetro |
Descrição |
|
|
arg_groups |
M |
Corresponde ao parâmetro Um valor maior aumenta a densidade do grafo, o que geralmente melhora o recall, mas também eleva o tempo de criação do índice e de consulta. |
|
efConstruction |
Corresponde ao parâmetro Valores maiores tendem a melhorar o recall, porém aumentam o tempo de criação do índice e de consulta. |
|
|
query_args |
ef_search |
Configuração de tempo de consulta que especifica o tamanho do conjunto de candidatos mantido durante o processo de busca. Um valor maior geralmente melhora o recall, mas também aumenta o tempo de consulta. |
Etapa 3: Criar a imagem Docker de teste
-
(Opcional) Para pular o teste da versão comunitária do PostgreSQL (padrão), altere o arquivo
~/ann-benchmarks/ann_benchmarks/algorithms/pgvector/Dockerfileconforme abaixo:FROM ann-benchmarks USER root RUN pip install psycopg[binary] pgvector -
Execute install.py com
--algorithm pgvectorpara criar a imagem Docker de teste.cd ~/ann-benchmarks/ python install.py --algorithm pgvectorNotaPara visualizar os parâmetros suportados, execute
python install.py --help.
Etapa 4: Obter o conjunto de dados
O script de benchmark baixa automaticamente o conjunto de dados público especificado.
Este tópico usa o conjunto de dados nytimes-256-angular, que emprega o tipo de distância Angular, como exemplo de busca por similaridade de texto. Para mais conjuntos de dados públicos, consulte ann-benchmarks.
|
Conjunto de dados |
Dimensão |
Número de linhas |
Vetores de teste |
Top-N vizinhos |
Tipo de distância |
|
NYTimes |
256 |
290.000 |
10.000 |
100 |
Angular |
Caso o conjunto de dados público não atenda às suas necessidades de teste, recomendamos converter seus dados vetoriais reais para um formato padrão como HDF5 a fim de testar o desempenho de recuperação. Para mais informações, consulte Appendix II: Custom Test Datasets.
Etapa 5: Executar o teste e obter resultados
-
Use os comandos a seguir para executar o script de benchmark.
cd ~/ann-benchmarks nohup python run.py --dataset nytimes-256-angular -k 10 --algorithm pgvector --runs 1 > ann_benchmark_test.log 2>&1 & tail -f ann_benchmark_test.logParâmetro
Descrição
--dataset
Especifica o conjunto de dados a ser testado.
--k
O valor LIMIT na instrução SQL de consulta, correspondente ao número de resultados a retornar.
--algorithm
O algoritmo de banco de dados vetorial a ser testado. Defina como pgvector para este teste.
--runs
O número de execuções do teste. O melhor resultado entre as execuções é selecionado.
--parallelism
A simultaneidade do teste. O padrão é 1.
-
Execute o comando abaixo para gerar um gráfico dos resultados do teste.
cd ~/ann-benchmarks python plot.py --dataset nytimes-256-angular --recomputeConcentre-se nas métricas de criação do índice e nos ganhos de desempenho para o mesmo recall.
Comparação de criação de índice:
Tipo de índice
Tempo de criação (s)
Tamanho do índice
Versão comunitária HNSW (v0.8.0)
127,89
7820 MB
Versão RDS HNSW (v0.8.0.1)
77,72
3916 MB
Comparação de QPS com o mesmo recall:
Recall
Parâmetros HNSW v0.8.0
Parâmetros HNSW v0.8.0.1
QPS v0.8.0
QPS v0.8.0.1
97%
ef_search=10
ef_search=10
1635,41
1954,48
98%
ef_search=30
ef_search=20
1075,49
1379,61
99,3%
ef_search=120
ef_search=80
434,74
737,06
99,5%
ef_search=300
ef_search=350
200,06
319,19
99,6%
ef_search=500
ef_search=500
109,51
177,94
-
(Opcional) Execute o comando a seguir para exportar os resultados detalhados do teste para um arquivo CSV.
cd ~/ann-benchmarks python data_export.py --out res.csvPor exemplo, você pode analisar a relação entre os parâmetros
m,ef_constructione o tempo de criação do índice:m
ef_construction
Tempo de criação (s)
16
100
33,35161
16
200
57,66014
24
200
87,22608
Conclusões
Ao criar um índice HNSW:
Aumentar
m,ef_constructioneef_searchpode melhorar a taxa de recall, mas reduzirá o QPS.Elevar
meef_constructiontambém aumenta a taxa de recall, ao mesmo tempo que diminui o QPS e prolonga o tempo de criação do índice.Se sua aplicação exigir uma alta taxa de recall, evite os parâmetros de índice padrão (m=16, ef_construction=64 e ef_search=40).
Apêndice I: RDS for PostgreSQL: Impacto dos parâmetros na criação de índices
Este apêndice utiliza resultados de testes do ann-benchmarks para demonstrar como diversos parâmetros do RDS for PostgreSQL e de vetores afetam a criação de índices.
RDS for PostgreSQL: Impacto dos parâmetros na criação de índices
Por exemplo, quando os parâmetros de teste do ann-benchmarks são definidos como m=16 e efConstruction=64, os parâmetros do RDS for PostgreSQL afetam a criação do índice da seguinte forma.
-
maintenance_work_mem
Este parâmetro especifica a memória máxima em kilobytes (KB) para operações de manutenção, como
VACUUMeCREATE INDEX. **Quando o valor demaintenance_work_memé menor que o tamanho do conjunto de dados, aumentá-lo reduz o tempo de criação do índice. No entanto, assim que o valor excede o tamanho do conjunto de dados, o tempo de criação não diminui mais.**Por exemplo, em uma instância RDS for PostgreSQL do tipo pg.x8.2xlarge.2c (16 núcleos, 128 GB), com o parâmetro
max_parallel_maintenance_workersdefinido com o valor padrão de 8 e usando o conjunto de dados nytimes-256-angular (aproximadamente 324 MB), o parâmetromaintenance_work_memafeta a criação do índice conforme abaixo:maintenance_work_mem
Tempo de criação do índice (s)
64 MB (65536 KB)
52,82
128 MB (131072 KB)
46,79
256 MB (262144 KB)
36,40
512 MB (524288 KB)
18,90
1 GB (1048576 KB)
19,06
-
max_parallel_maintenance_workers
Este parâmetro define o número máximo de workers paralelos para
CREATE INDEX. **O tempo de criação do índice diminui à medida quemax_parallel_maintenance_workersaumenta.**Por exemplo, em uma instância RDS for PostgreSQL do tipo pg.x8.2xlarge.2c (16 núcleos, 128 GB), com o parâmetro
maintenance_work_memdefinido como 2 GB (2048 MB) e usando o conjunto de dados nytimes-256-angular (aproximadamente 324 MB), o parâmetromax_parallel_maintenance_workersafeta a criação do índice da seguinte maneira:max_parallel_maintenance_workers
Tempo de criação do índice (s)
1
76,00
2
51,34
4
32,49
8
19,66
12
14,44
16
13,07
24
13,15
Impacto dos parâmetros de vetor na criação de índices
Com os parâmetros do RDS for PostgreSQL definidos como maintenance_work_mem=8 GB (8388608 KB) e max_parallel_maintenance_workers=16, as seções a seguir mostram o impacto dos parâmetros de vetor na criação de índices.
-
Dimensão do vetor
Os testes a seguir usam o conjunto de dados GloVe (1.183.514 vetores) com os parâmetros de teste do ann-benchmarks definidos como
m=16,efConstruction=64eef_search=40. Os resultados mostram que, à medida que a dimensão do vetor aumenta, o tempo de criação do índice e a latência de consulta também aumentam, enquanto tanto o recall quanto o QPS diminuem.Dimensão
Tempo de criação (s)
Recall
QPS
p99 (ms)
25
195,10
0,99985
192,94
7,84
50
236,92
0,99647
152,36
9,69
100
319,36
0,97231
126,89
11,14
200
529,33
0,93186
95,05
15,11
NotaO percentil 99 da latência de consulta. Isso significa que 99% das solicitações de consulta são concluídas em menos tempo que este valor, e apenas 1% demoram mais.
-
Número de vetores
Estes testes utilizam a série de conjuntos de dados
dbpedia-openai-{n}k-angular, ondenrepresenta o número de vetores em milhares (de 100 a 1.000). Quando os parâmetros de teste do ann-benchmarks são definidos comom=48,efConstruction=256eef_search=200, os resultados são os seguintes. Os dados indicam que o tempo de criação do índice aumenta de forma não linear conforme o número de vetores cresce, enquanto tanto o recall quanto o QPS diminuem e a latência de consulta aumenta.Número de vetores
Número de linhas (x10.000)
Tempo de criação (s)
Recall
QPS
p99 (ms)
100
10
54,05
0,9993
171,74
8,93
200
20
137,23
0,99901
146,78
10,81
500
50
436,68
0,999
118,55
13,94
1000
100
957,26
0,99879
101,60
16,35
Apêndice II: Conjunto de dados de teste personalizado
O exemplo a seguir mostra como criar um conjunto de dados baseado no formato de dados nytimes-256-angular.
-
Execute o script abaixo para criar um conjunto de dados de teste personalizado.
NotaEste exemplo requer a extensão rds_ai. Para mais informações, consulte AI (rds_ai).
import h5py import numpy as np import psycopg2 import pgvector.psycopg2 # Connection details conn_info = { 'host': 'pgm-****.rds.aliyuncs.com', 'user': 'ann_testuser', 'password': '****', 'port': '5432', 'dbname': 'ann_testdb' } embedding_len = 1024 distance_top_n = 100 query_batch_size = 100 try: # Connect to the RDS for PostgreSQL database with psycopg2.connect(**conn_info) as connection: pgvector.psycopg2.register_vector(connection) with connection.cursor() as cur: # Fetch the vector data cur.execute("select count(1) from test_rag") count = cur.fetchone()[0] train_embeddings = [] for start in range(0, count, query_batch_size): query = f"SELECT embedding FROM test_rag ORDER BY id OFFSET {start} LIMIT {query_batch_size}" cur.execute(query) res = [embedding[0] for embedding in cur.fetchall()] train_embeddings.extend(res) train = np.array(train_embeddings) # Get query data and compute embeddings with open('query.txt', 'r', encoding='utf-8') as file: queries = [query.strip() for query in file] test = [] # Install the rds_ai extension or use the Alibaba Cloud Model Studio SDK for query in queries: cur.execute(f"SELECT rds_ai.embed('{query.strip()}')::vector(1024)") test.extend([cur.fetchone()[0]]) test = np.array(test) # Calculate the top N nearest neighbor distances dot_product = np.dot(test, train.T) norm_test = np.linalg.norm(test, axis=1, keepdims=True) norm_train = np.linalg.norm(train, axis=1, keepdims=True) similarity = dot_product / (norm_test * norm_train.T) distance_matrix = 1 - similarity neighbors = np.argsort(distance_matrix, axis=1)[:, :distance_top_n] distances = np.take_along_axis(distance_matrix, neighbors, axis=1) with h5py.File('custom_dataset.hdf5', 'w') as f: f.create_dataset('distances', data=distances) f.create_dataset('neighbors', data=neighbors) f.create_dataset('test', data=test) f.create_dataset('train', data=train) f.attrs.update({ "type": "dense", "distance": "angular", "dimension": embedding_len, "point_type": "float" }) print("The HDF5 file was created successfully and the dataset was added.") except (Exception, psycopg2.DatabaseError) as error: print(f"Error: {error}") -
Registre seu conjunto de dados de teste personalizado na seção
DATASETSdo arquivo~/ann-benchmarks/ann_benchmarks/datasets.py.DATASETS: Dict[str, Callable[[str], None]] = { ......, "<custom_dataset>": None, } Faça upload do conjunto de dados de teste personalizado para o diretório
~/ann-benchmarks. Em seguida, você poderá usar o conjunto de dados com o script de testerun.py.