Bruce Lindsay disse uma vez"Há três coisas importantes no mundo dos bancos de dados: Desempenho, desempenho e desempenho". A maioria dos arquitetos corporativos sabe que, à medida que avançamos nos recursos e nas arquiteturas de banco de dados, é importante medir o desempenho de forma aberta para que eles possam comparar o custo total de propriedade de forma confiável.
YCSB fez um excelente trabalho de benchmarking de armazenamentos de dados que atendem aos aplicativos "Cloud OLTP". Esses armazenamentos de dados eram simples, com operações simples de obter, colocar e excluir. A versão original Referência YCSB consiste em operações simples de inserção, atualização, exclusão e varredura em um documento simples de 10 valores-chave; as cargas de trabalho são definidas com uma combinação dessas operações em várias porcentagens.
JSON bancos de dados como Couchbase e MongoDB têm um modelo de dados mais avançado com escalares, objetos aninhados, matrizes, matrizes de objetos, matrizes e matrizes de objetos. Os bancos de dados JSON também têm consulta linguagem, índices e recursos. Além das operações de CRUD, os aplicativos usam rotineiramente as linguagens de consulta declarativas nesses bancos de dados para pesquisar, paginar e executar relatórios. Portanto, para ajudar os arquitetos a avaliar as plataformas de forma eficaz, precisamos de um benchmark adicional para medir esses recursos, além das operações básicas de CRUD. Este tutorial do YCSB explica seus recursos para preencher essa lacuna.
Papel YCSB estados: Também esperamos promover o desenvolvimento de outros conjuntos de benchmark de nuvem que representem outras classes de aplicativos, disponibilizando nossa ferramenta de benchmark por meio de código aberto. Nesse sentido, um dos principais recursos da estrutura/ferramenta YCSB é o fato de ser extensível - ela suporta a definição fácil de novas cargas de trabalho, além de facilitar a avaliação comparativa de novos sistemas.
Esse benchmark estende o YCSB para bancos de dados JSON, ampliando as operações existentes para JSON e, em seguida, definindo novas operações e novas cargas de trabalho.
Aqui está o esboço.
- Introdução
- Modelo de dados
- Operações de referência
- Cargas de trabalho de referência
- Implementação do YCSB-JSON
- Como executar o YCSB-JSON?
- Referências
1. Introdução
O YCSB foi desenvolvido para medir o desempenho de armazenamentos de dados de valor-chave NoSQL dimensionáveis. A infraestrutura do YCSB faz bem esse trabalho. O YCSB usa uma chave-valor simples e plana. O Couchbase usa um modelo JSON, que os clientes usam para aplicativos interativos em massa. Criamos e estamos criando recursos no produto para permitir que os clientes criem esses aplicativos de forma eficaz. Precisamos de medições de desempenho para esses casos de uso.
Há outros bancos de dados compatíveis com o modelo JSON: MongoDB, DocumentDB, DynamoDB, RethinkDB, Oracle NoSQL. Ao executar o YCSB em bancos de dados JSON (Couchbase, MongoDB etc.), o driver simplesmente armazena e recupera cadeias de caracteres na estrutura de valor-chave JSON. Todos esses bancos de dados exigem um novo benchmark para medir o processamento da estrutura avançada do JSON (objetos aninhados, matrizes) e operações como paginação, agrupamento e agregações.
O objetivo do YCSB-JSON é estender o benchmark YCSB para medir a capacidade do banco de dados JSON para cobrir esses dois aspectos:
- Representante de operações de aplicativos interativos em massa.
- Operações no modelo de dados JSON, incluindo objetos aninhados e matrizes.
- Crie cargas de trabalho que representem as operações desses aplicativos.
Veja estes casos de uso de clientes:
- Marriott criou seu sistema de reservas no IBM Mainframe e no DB2. Eles enfrentaram desafios de custo e desempenho à medida que mais e mais clientes tentavam navegar pelo inventário disponível. Os sistemas em DB2 foram originalmente criados para receber reservas de um sistema telefônico ou de agentes. A taxa de procura por reserva é baixa. Atualmente, essa proporção é alta, pois o número de solicitações de pesquisa aumentou exponencialmente. Isso também aumentou drasticamente o custo do banco de dados. A Marriott transferiu todos os seus dados de inventário para o Couchbase com sincronização contínua de seus sistemas de mainframe; os aplicativos da Web usam o Couchbase para as operações de consulta/pesquisa.
- Carros.com é um portal para listar e vender carros. Eles têm os dados de listagem no Oracle. Quando os disponibilizam na Web, eles precisam não apenas apresentar as informações básicas sobre o carro, mas também fornecer insights adicionais, como quantos usuários estão procurando um carro ou o salvaram em sua lista de desejos. Essa é uma forma de aumentar o envolvimento e o senso de urgência. Todos os dados necessários para essas operações interativas são armazenados no Couchbase.
De modo mais geral, os aplicativos interativos em massa incluem o seguinte:
- Consulte a disponibilidade de quartos, detalhes de preços, comodidades (pesquisas por clientes finais)
- Procurar informações sobre marca/modelo de carro ou oficinas de reparo (habilitar consumidores e parceiros em escala da Web)
- Fornecer informações ao cliente no contexto (serviços baseados em localização)
- Atende tanto aos dados mestre quanto aos dados transacionais (em escala)
Para dar suporte a esses requisitos, os aplicativos e bancos de dados fazem o seguinte:
- Descarga de consultas de bancos de dados de sistemas de registro de alto custo (mainframe, Oracle)
- (aplicativos de reservas e receitas)
- Abertura das funções de back-office para acesso à Web/móvel
- (permitir que os usuários da Web verifiquem os detalhes do quarto)
- Dimensione o banco de dados/consultas com melhor TCO
- (dimensionar mainframes com servidores de commodities)
- Modernize os sistemas legados com os recursos exigidos pelos novos aplicativos de colaboração/engajamento
- (inventário de navegação, voos, disponibilidade de quartos, análise departamental)
O novo benchmark precisa medir o desempenho das consultas que implementam essas operações.
2. Modelo de dados
Consideramos o cliente e os pedidos como duas coleções distintas de documentos JSON. Cada pedido tem uma referência ao seu cliente.
Abaixo estão os exemplos de cliente e documento de pedido. Eles foram gerados por meio do gerador de dados fakeit. Essa ferramenta está disponível em: https://github.com/bentonam/fakeit
Consulte o apêndice para ver o arquivo YAML usado para definir o modelo de dados e o domínio.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Sample customer document Document Key: 100_advjson { "_id": "100_advjson", "doc_id": 100, "gid": "48a8e177-15e5-5116-95d0-41478601bbdd", "first_name": "Stella", "middle_name": "Jackson", "last_name": "Toy", "ballance_current": "$1084.94", "dob": "2016-05-11", "email": "Alysson83@yahoo.com", "isActive": true, "linear_score": 31, "weighted_score": 40, "phone_country": "fr", "phone_by_country": "01 80 03 25 39", "age_group": "child", |
3. Operações de referência:
As quatro primeiras operações são iguais às do YCSB padrão, exceto pelo fato de que se trata de documentos JSON. O restante das operações é novo.
- Inserir: Insere um novo documento JSON.
- Atualização: Atualize um documento JSON substituindo o valor de um campo escalar.
- Ler: Lê um documento JSON, seja um campo escolhido aleatoriamente ou todos os campos.
- Excluir: Exclui um documento JSON com uma determinada chave.
- Escaneamento: Digitaliza documentos JSON em ordem, começando por uma chave de registro escolhida aleatoriamente. O número de registros a serem digitalizados é escolhido aleatoriamente (LIMIT).
- Pesquisa: Pesquise documentos JSON com base em predicados de intervalo em 3 campos (personalizável para n campos).
- Página: Paginar o conjunto de resultados de uma consulta com predicado em um campo do documento.
- Todos os clientes em zip com OFFSET e LIMIT escolhidos aleatoriamente em SQL, N1QL.
- NestScan: Consulta a documentos JSON com base em um predicado em um campo aninhado de 1 nível.
- ArrayScan: Consulta de documentos JSON com base em um predicado dentro do campo de matriz de nível único.
- ArrayDeepScan: Consulta de documentos JSON com base em um predicado em um campo de matriz de dois níveis (matriz de matrizes).
- Relatório: Consultar detalhes de pedidos de clientes em um código postal específico.
- Cada cliente tem vários pedidos.
- O documento do pedido contém detalhes do pedido.
- Relatório2: Gerar resumo de pedidos de vendas para um determinado dia, agrupado por CEP.
- Carga: Carregamento de dados.
- Sincronização: Transmissão e sincronização de dados de outro sistema.
- Agregado: Faça alguns agrupamentos e agregações.
Para o Couchbase: Exemplos de implementação de operações de benchmark
As quatro primeiras operações são iguais às do YCSB padrão, exceto pelo fato de que se trata de documentos JSON. O restante das operações é novo.
O Couchbase implementa o YCSB em dois modos.
KV=verdadeiro. KV significa key-value (valor-chave). As operações simples INSERT, UPDATE e DELETE do YCSB podem ser implementadas por meio de APIs KV em vez de consultas. Definir KV=true significa usar a API KV e KV=false significa usar a API N1QL (SQL para JSON). Veja o tutorial do N1QL em https://query-tutorial.couchbase.com
- Inserir: Insere um novo documento JSON.
|
1 2 |
KV=true: KV call to insert KV=false: INSERT INTO customer VALUES(...) |
2. Atualização: Atualize um documento JSON substituindo o valor de um campo escalar.
|
1 2 3 4 |
KV=true: KV call to UPDATE a single document. KV=false: UPDATE customer SET field1 = value USE KEYS [documentkey]<span style="font-weight: 400"><strong>Read</strong>: Read a JSON document, either one randomly chosen field in the document or all the fields.</span> |
|
1 2 3 4 |
KV=true: KV call to fetch a single document. KV=false: SELECT * FROM customer USE KEYS [documentkey] |
3. Leia: Obtém um documento JSON com uma determinada chave.
|
1 2 3 4 |
KV=true: KV call to fetch a single document. KV=false: SELECT * FROM customer USE KEYS [documentkey] |
4. Excluir: Exclui um documento JSON com uma determinada chave.
|
1 2 3 4 |
KV=true: KV call to fetch a single document. KV=false: DELETE FROM customer USE KEYS [documentkey] |
5. Digitalização: Digitaliza documentos JSON em ordem, começando por uma chave de registro escolhida aleatoriamente. O número de registros a serem digitalizados é escolhido aleatoriamente (LIMIT).
|
1 2 3 4 5 6 7 |
KV=TRUE: SELECT META().id FROM customer WHERE META().id > “val” ORDER BY META().id LIMIT <num> Fetch the actual documents directly using KV calls from the benchmark driver. KV=false: SELECT * FROM customer WHERE META().id > “val” ORDER BY META().id LIMIT <num> |
6. Página: Paginar o conjunto de resultados de uma consulta com predicado em um campo do documento.
|
1 2 3 4 5 6 7 8 9 10 |
All customers in address.zip with randomly chosen OFFSET and LIMIT in SQL, N1QL KV=TRUE: SELECT META().id FROM customer WHERE address.zip = “value” OFFSET <num> LIMIT <num> Fetch the actual documents directly using KV calls from the benchmark driver. KV=false: SELECT * FROM customer WHERE address.zip = “value” OFFSET <num> LIMIT <num> |
7. Busca: Pesquisar documentos JSON com base em predicados de intervalo em 3 campos (personalizável para n campos).
|
1 2 3 4 5 6 7 8 9 10 11 12 |
All customers WHERE (country = “value1” AND age_group = “value2” and YEAR(dob) = “value” ) All customers retrieved with randomly chosen OFFSET and LIMIT in SQL, N1QL KV=TRUE: SELECT META().id FROM customer WHERE country = “value1” AND age_group = “value2” and YEAR(dob) = “value” ORDER BY country, age_group, YEAR(dob) OFFSET <num> LIMIT <num> Fetch the actual documents directly using KV calls from the benchmark driver. KV=false: SELECT * FROM customer WHERE WHERE country = “value1” AND age_group = “value2” and YEAR(dob) = “value” ORDER BY country, age_group, YEAR(dob) OFFSET <num> LIMIT <num> |
8. NestScan: Consulta a documentos JSON com base em um predicado em um campo aninhado de 1 nível.
|
1 2 3 4 5 6 7 8 9 |
KV=TRUE: SELECT META().id FROM customer WHERE address.prev_address.zip = “value” LIMIT <num> Fetch the actual documents directly using KV calls from the benchmark driver. KV=false: SELECT * FROM customer WHERE address.prev_address.zip = “value” LIMIT <num> |
9. ArrayScan: Consulta de documentos JSON com base em um predicado dentro do campo de matriz de nível único.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Find all customers who have devices with a value. E.g. FF-012 Sample devices field "devices": [ "EE-245", "FF-012", "GG-789", "HH-246" ], KV=TRUE: SELECT META().id FROM customer WHERE ANY v IN devices SATISFIES v = “FF-012” END ORDER BY META().id LIMIT <num> Fetch the actual documents directly using KV calls from the benchmark driver. KV=false: SELECT * FROM customer WHERE ANY v IN devices SATISFIES v = “FF-012” ORDER BY META().id END LIMIT <num> |
10. ArrayDeepscan: Consulta de documentos JSON com base em um predicado em um campo de matriz de dois níveis (matriz de matrizes).
- Obtenha uma lista de todos os clientes que visitaram Paris, França.
KV=verdadeiro:
|
1 2 3 4 5 6 7 8 |
SELECT META().id FROM customer WHERE ANY v in visited_places SATISFIES v.country = “France” AND ANY c in v.cities SATISFIES c = “Paris” END ORDER BY META().id LIMIT <num> |
Obtenha os documentos reais diretamente usando chamadas KV do driver de benchmark.
KV=false:
|
1 2 3 4 5 6 7 8 |
SELECT * FROM customer WHERE ANY v in visited_places SATISFIES v.country = “France” AND ANY c in v.cities SATISFIES c = “Paris” END END ORDER BY META().id LIMIT <num> |
11. Relatório: Consultar detalhes de pedidos de clientes em um código postal específico.
-
123456789101112131415161718Each customer has multiple orders.Order document has order details.KV=TRUE:Not possible (easily without significant perf impact.KV=false:SELECT *FROM customer c INNER JOIN orders oON (META(id) IN c.order_list)WHERE address.zip = "val"ANSI JOIN with HASH join:SELECT *FROM customer c INNER JOIN orders o USE HASH (probe)ON (META(id) IN c.order_list)WHERE address.zip = “val”
12. Relatório2: Gerar resumo de pedidos de vendas para um determinado dia, agrupado por CEP.
|
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 |
KV=TRUE: Need to write a program KV=false: SELECT o.day, c.zip, SUM(o.salesamt) FROM customer c INNER JOIN orders o ON (META(id) IN c.order_list) WHERE c.zip = “value” AND o.day = “value” GROUP BY c.day, c.zip ORDER BY SUM(o.sales_amt) ----ANSI join SELECT o.day, c.zip, SUM(o.salesamt) FROM customer c INNER JOIN orders o ON (META(id) IN c.order_list) WHERE c.zip = “value” AND o.day = “value” GROUP BY c.day, c.zip ORDER BY SUM(o.sales_amt) ------ANSI join with HASH join SELECT o.day, c.zip, SUM(o.salesamt) FROM customer c INNER JOIN orders o USE HASH (probe) ON (META(id) IN c.order_list) WHERE c.zip = “value” AND o.day = “value” GROUP BY c.day, c.zip ORDER BY SUM(o.sales_amt) |
13. Carga: Carregamento de dados.
- CARREGAR 1 milhão de documentos.
- CARREGAR 10 milhões de documentos.
14. Sincronização: Transmissão e sincronização de dados de outro sistema
- Necessidade de medir o desempenho da sincronização de dados.
- Sincronização de 1 milhão de documentos. Atualização do 50%, inserção do 50%.
- Sincronização de 10 milhões de documentos. Atualização 80%, inserção 20%.
- O ideal é que essa sincronização seja feita a partir do Kafka ou de algum outro conector que extraia dados de uma fonte diferente.
15. Agregado: Faça alguns agrupamentos e agregações.
|
1 2 3 4 5 6 |
---Group Query 1 SELECT c.zip, COUNT(1) FROM customer c WHERE c.zip between "value1" and "value2" GROUP BY c.zip |
|
1 2 3 4 5 6 7 8 9 10 |
---GROUP BY query 2 SELECT o.day, SUM(o.salesamt) FROM orders o WHERE o.day between “value1” and “value2” GROUP BY o.day; |
4. Cargas de trabalho de referência
As cargas de trabalho são uma combinação dessas operações.
Para começar, a definição da carga de trabalho pode reutilizar as definições da definição do YCSB: carga de trabalho A até carga de trabalho E. Os detalhes estão disponíveis em https://github.com/brianfrankcooper/YCSB/wiki/Core-Workloads. Precisaremos definir cargas de trabalho adicionais com uma combinação das operações definidas acima.
A carga de trabalho SA é a mesma que a carga de trabalho A no novo modelo. O mesmo acontece com a carga de trabalho de B a F. Vamos chamá-las de SB a SF para diferenciar da carga de trabalho de B a F.
| Carga de trabalho | Operações | Seleção de registros | Exemplo de aplicativo |
| SA - Atualização pesada | Leia: 50%
Atualização 50% |
Zipfiano | Armazenamento de sessão que registra ações recentes em uma sessão de usuário |
| SB - Ler pesado | Ler: 95%
Atualização: 5% |
Zipfiano | Marcação de fotos; adicionar uma tag é uma atualização, mas a maioria das operações
Atualização: 5% são para ler etiquetas |
| SC - Somente leitura | Ler: 100% | Zipfiano | Cache de perfil de usuário, em que os perfis são construídos em outro lugar (por exemplo, Hadoop) |
| SD - Leia mais recente | Ler: 95%
Inserto 5% |
Mais recentes | Atualizações de status do usuário; as pessoas querem ler os status mais recentes |
| SE - Alcances curtos | Escanear: 95%
Inserção: 5% |
Zipfian/Uniforme | Conversas encadeadas, em que cada varredura é para as postagens em um determinado encadeamento (supostamente agrupadas por ID de encadeamento) |
| SF - Ler, modificar, gravar | Leia: 50%
Escreva: 50% |
Zipfiano | banco de dados de usuários, em que os registros de usuários são lidos e modificados pelo usuário ou para registrar a atividade do usuário. |
| SG - Página pesada | Página: 90%
Inserção: 5% Atualização:5% |
Zipfiano | Banco de dados de usuários, onde novos usuários são adicionados, registros existentes são atualizados, consultas de paginação no sistema. |
| SH - Pesquisa pesada | Busca: 90%
Inserção: 5% Atualização: 5% |
Zipfiano | Banco de dados de usuários, onde novos usuários são adicionados, registros existentes são atualizados e consultas de pesquisa no sistema. |
| SI - NestScan pesado | Nestscan: 90%
Inserção: 5% Atualização: 5% |
Zipfiano | Banco de dados de usuários, onde novos usuários são adicionados, registros existentes são atualizados, consultas de nestscan no sistema. |
| SJ - Arrayscan pesado | Arrayscan: 90%
Inserção: 5% Atualização: 5% |
Zipfiano | |
| SK - ArrayDeepscan pesado | ArrayDeepScan: 90%
Inserção: 5% Atualização: 5% |
Zipfiano | |
| SL - Relatório | Relatório: 100% | ||
| SL - Relatório2 | Relatório2: 100% | ||
| SLoad - Carga | Carga: 100% | Tudo | Carga de dados para configurar o SoE |
| SN - Agregado
(SN1, SN2) |
Agregação: 90%
Inserção: 5% Atualização: 5% |
||
| SMIX - Carga de trabalho mista | Página:20%
Busca:20% Arrayscan:15% MatrizDeepscan:10% Agregado: 10% Relatório: 10% |
Veja abaixo. | |
| SSync - Sincronização | Sincronização: 100%
Mesclar/Atualizar: 70% Novo/Inserto: 30% |
Sincronização contínua de dados de outros sistemas com os sistemas de engajamento. Veja abaixo. |
Exemplo de configuração para carga de trabalho YCSB/JSON
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
recordcount=1000 operationcount=1000 workload=com.yahoo.ycsb.workloads.CoreWorkload Filternumlow = 2 Filternumhigh = 14 Sortnumlow = 3 Sortnumhigh = 6 page1propotion=0.95 insertproportion=0.05 requestdistribution=zipfian maxscanlength=100 scanlengthdistribution=uniform |
Agradecimentos
Agradecimentos a Raju Suravarjjala, Ao diretor sênior de QE e desempenho do Couchbase, por nos incentivar a fazer isso, e a toda a equipe de desempenho por apoiar esse esforço. O benchmark YCSB-JSON foi desenvolvido em colaboração com Alex Gyryk, Engenheiro de desempenho principal do Couchbase. Ele desenvolveu os modelos de dados para clientes e pedidos usados neste artigo e implementou as operações e cargas de trabalho no YCSB-JSON para Couchbase e MongoDB. A implementação do YCSB-JSON está disponível em: https://github.com/couchbaselabs/YCSB
Agradecimentos a Aron Benton, Arquiteto de soluções do Couchase, por desenvolver um gerador de dados JSON fácil de usar e eficiente, o fakeit. Ele o desenvolveu antes de ingressar no Couchbase. Ele está disponível em: https://github.com/bentonam/fakeit
Próxima parte
No próximo artigo sobre o YCSB-JSON, Alex explicará as implementações desse benchmark para o Couchbase e o MongoDB. O código-fonte da implementação está disponível em: https://github.com/couchbaselabs/YCSB
Referências
- Benchmarking Cloud Serving Systems com YCSB: https://www.cs.duke.edu/courses/fall13/cps296.4/838-CloudPapers/ycsb.pdf
- JSON: https://json.org
- Gerador de JSON: https://www.json-generator.com/
- Implementação do YCSB-JSON: https://github.com/couchbaselabs/YCSB
Apêndice
YAML para gerar o conjunto de dados do cliente.
|
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 |
name: AdvJSON type: object key: _id data: fixed: 10000 properties: _id: type: string data: post_build: "return '' + this.doc_id + '_advjson';" doc_id: type: integer description: The document id data: build: "return document_index + 1" gid: type: description: "guid" data: build: "return chance.guid();" first_name: type: string description: "First name - string, linked to url as the personal page" data: |
Existe um YAML para pedidos para gerar o conjunto de dados de pedidos?
Também estou procurando por isso. O YAML no apêndice não contém a chave "order_list".
Olá, ótimo trabalho! Você poderia fornecer mais instruções sobre como chegar à implementação mencionada aqui? Acabei de verificar a ramificação principal de https://github.com/couchbaselabs/YCSB e não consigo encontrar nem as cargas de trabalho mencionadas aqui nem a implementação das novas operações.
Veja os detalhes no artigo de acompanhamento: https://www.couchbase.com/ycsb-json-implementation-for-couchbase-and-mongodb/
Incrível, obrigado!
Muito obrigado,
Por favor, tenho uma pergunta: como podemos gerar uma nova carga de trabalho com base em novos requisitos?