Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Comparação de desempenho do MySQL:MySQL 5.7 vs MySQL 8.0


O MySQL 8.0 trouxe enormes mudanças e modificações que foram promovidas pela Oracle MySQL Team. Os arquivos físicos foram alterados. Por exemplo, *.frm, *.TRG, *.TRN e *.par não existem mais. Toneladas de novos recursos foram adicionados, como CTE (Common Table Expressions), Window Functions, Invisible Indexes, regexp (ou Expression Regular) - o último foi alterado e agora fornece suporte total a Unicode e é seguro para vários bytes. O dicionário de dados também mudou. Agora está incorporado a um dicionário de dados transacionais que armazena informações sobre objetos de banco de dados. Ao contrário das versões anteriores, os dados do dicionário eram armazenados em arquivos de metadados e tabelas não transacionais. A segurança foi aprimorada com a nova adição de caching_sha2_password, que agora é a autenticação padrão substituindo mysql_native_password e oferece mais flexibilidade, mas segurança reforçada que deve usar uma conexão segura ou uma conexão não criptografada que suporta troca de senha usando um par de chaves RSA.

Com todos esses recursos interessantes, aprimoramentos e melhorias que o MySQL 8.0 oferece, nossa equipe estava interessada em determinar o desempenho da versão atual do MySQL 8.0, especialmente considerando que nosso suporte para as versões do MySQL 8.0.x no ClusterControl está a caminho (então fique atento nisto). Esta postagem de blog não discutirá os recursos do MySQL 8.0, mas pretende comparar seu desempenho com o MySQL 5.7 e ver como ele melhorou.

Configuração e ambiente do servidor


Para este benchmark, pretendo usar uma configuração mínima para produção usando o seguinte ambiente AWS EC2:

Tipo de instância:instância t2.xlarge
Armazenamento:gp2 (armazenamento SSD com mínimo de 100 e máximo de 16.000 IOPS)
vCPUS:4
Memória:16GiB
Versão MySQL 5.7:MySQL Community Server (GPL) 5.7.24
Versão MySQL 8.0:MySQL Community Server - GPL 8.0.14

Existem algumas variáveis ​​​​notáveis ​​​​que eu defini para este benchmark também, que são:
  • innodb_max_dirty_pages_pct =90 ## Este é o valor padrão no MySQL 8.0. Veja aqui os detalhes.
  • innodb_max_dirty_pages_pct_lwm=10 ## Este é o valor padrão no MySQL 8.0
  • innodb_flush_neighbors=0
  • innodb_buffer_pool_instances=8
  • innodb_buffer_pool_size=8GiB

O resto das variáveis ​​que estão sendo definidas aqui para ambas as versões (MySQL 5.7 e MySQL 8.0) já estão ajustadas pelo ClusterControl para seu template my.cnf.

Além disso, o usuário que usei aqui não está em conformidade com a nova autenticação do MySQL 8.0 que usa caching_sha2_password. Em vez disso, ambas as versões do servidor usam mysql_native_password mais a variável innodb_dedicated_server está OFF (padrão), que é um novo recurso do MySQL 8.0.

Para tornar a vida mais fácil, eu configurei o nó da versão MySQL 5.7 Community com ClusterControl de um host separado, em seguida, removi o nó em um cluster e desliguei o host ClusterControl para tornar o nó MySQL 5.7 inativo (sem monitoramento de tráfego). Tecnicamente, ambos os nós MySQL 5.7 e MySQL 8.0 estão inativos e nenhuma conexão ativa está passando pelos nós, então é essencialmente um teste de benchmarking puro.

Comandos e scripts usados


Para esta tarefa, o sysbench é usado para teste e simulação de carga para os dois ambientes. Aqui estão os seguintes comandos ou script sendo usados ​​neste teste:

sb-prepare.sh
#!/bin/bash

host=$1
#host192.168.10.110
port=3306
user='sysbench'
password='[email protected]'
table_size=500000
rate=20
ps_mode='disable'
sysbench /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --threads=1 --max-requests=0 --time=3600 --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --tables=10 --report-interval=1 --skip-trx=on --table-size=$table_size --rate=$rate --db-ps-mode=$ps_mode prepare

sb-run.sh
#!/usr/bin/env bash

host=$1
port=3306
user="sysbench"
password="[email protected]"
table_size=100000
tables=10
rate=20
ps_mode='disable'
threads=1
events=0
time=5
trx=100
path=$PWD

counter=1

echo "thread,cpu" > ${host}-cpu.csv

for i in 16 32 64 128 256 512 1024 2048; 
do 

    threads=$i

    mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
    tmpfile=$path/${host}-tmp${threads}
    touch $tmpfile
    /bin/bash cpu-checker.sh $tmpfile $host $threads &

    /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql --events=$events --threads=$threads --time=$time --mysql-host=$host --mysql-user=$user --mysql-password=$password --mysql-port=$port --report-interval=1 --skip-trx=on --tables=$tables --table-size=$table_size --rate=$rate --delete_inserts=$trx --order_ranges=$trx --range_selects=on --range-size=$trx --simple_ranges=$trx --db-ps-mode=$ps_mode --mysql-ignore-errors=all run | tee -a $host-sysbench.log

    echo "${i},"`cat ${tmpfile} | sort -nr | head -1` >> ${host}-cpu.csv
    unlink ${tmpfile}

    mysql -h $host -e "SHOW GLOBAL STATUS" >> $host-global-status.log
done

python $path/innodb-ops-parser.py $host

mysql -h $host -e "SHOW GLOBAL VARIABLES" >> $host-global-vars.log

Assim, o script simplesmente prepara o esquema sbtest e preenche tabelas e registros. Em seguida, ele executa testes de carga de leitura/gravação usando o script /usr/share/sysbench/oltp_read_write.lua. O script despeja o status global e as variáveis ​​do MySQL, coleta a utilização da CPU e analisa as operações de linha do InnoDB tratadas pelo script innodb-ops-parser.py. Os scripts então geram arquivos *.csv com base nos logs despejados que foram coletados durante o benchmark, então usei uma planilha do Excel aqui para gerar o gráfico a partir de arquivos *.csv. Por favor, verifique o código aqui neste repositório do github.

Agora, vamos prosseguir com os resultados do gráfico!

Operações de linha do InnoDB


Basicamente aqui, eu extraí apenas as operações de linha do InnoDB que fazem as seleções (leituras), exclusões, inserções e atualizações. Quando o número de threads aumenta, o MySQL 8.0 supera significativamente o MySQL 5.7! Ambas as versões não têm nenhuma alteração de configuração específica, mas apenas as variáveis ​​​​notáveis ​​que defini. Portanto, ambas as versões estão usando valores padrão.

Curiosamente, no que diz respeito às afirmações do MySQL Server Team sobre o desempenho de leituras e escritas na nova versão, os gráficos apontam para uma melhoria significativa de desempenho, especialmente em um servidor de alta carga. Imagine a diferença entre MySQL 5.7 versus MySQL 8.0 para todas as suas operações de linha InnoDB, há uma grande diferença especialmente quando o número de threads aumenta. O MySQL 8.0 revela que pode ter um desempenho eficiente independentemente de sua carga de trabalho.

Transações processadas


Conforme mostrado no gráfico acima, o desempenho do MySQL 8.0 mostra novamente uma enorme diferença no tempo que leva para processar as transações. Quanto menor, melhor o desempenho, o que significa que é mais rápido processar as transações. As transações processadas (o segundo gráfico) também revelam que ambos os números de transações não diferem entre si. Ou seja, ambas as versões executam quase o mesmo número de transações, mas diferem na rapidez com que podem ser concluídas. Embora eu possa dizer, o MySQL 5.7 ainda pode lidar muito com carga mais baixa, mas a carga realista, especialmente na produção, pode ser mais alta - especialmente no período mais movimentado.

O gráfico acima ainda mostra as transações que ele conseguiu processar, mas separa a leitura das gravações. No entanto, existem discrepâncias nos gráficos que não incluí, pois são pequenos detalhes do resultado que distorceriam o gráfico.

O MySQL 8.0 revela grandes melhorias especialmente para fazer leituras. Ele exibe sua eficiência nas gravações especialmente para servidores com alta carga de trabalho. Um ótimo suporte adicionado que afeta o desempenho do MySQL para leituras na versão 8.0 é a capacidade de criar um índice em ordem decrescente (ou varreduras de índice para frente). Versões anteriores tinham apenas varredura de índice ascendente ou retrógrado, e o MySQL tinha que fazer filesort se precisasse de uma ordem decrescente (se filesort for necessário, você pode considerar verificar o valor de max_length_for_sort_data). Índices decrescentes também possibilitam que o otimizador use índices de várias colunas quando a ordem de varredura mais eficiente combina ordem crescente para algumas colunas e ordem decrescente para outras. Veja aqui para mais detalhes.

Recursos de CPU


Durante este benchmark, decidi tirar alguns recursos de hardware, mais notavelmente, a utilização da CPU.

Deixe-me explicar primeiro como eu uso o recurso CPU aqui durante o benchmarking. O sysbench não inclui estatísticas coletivas para recursos de hardware utilizados ou usados ​​durante o processo quando você está comparando um banco de dados. Por causa disso, o que eu fiz foi criar um sinalizador criando um arquivo, conectar-se ao host de destino por meio de SSH e, em seguida, coletar dados do comando Linux “top” e analisá-los enquanto dormia por um segundo antes de coletar novamente. Depois disso, pegue o aumento mais notável do uso da CPU para o processo mysqld e remova o arquivo sinalizador. Você pode revisar o código que tenho no github.

Então vamos discutir novamente sobre o resultado do gráfico, parece revelar que o MySQL 8.0 consome muita CPU. Mais do que o MySQL 5.7. No entanto, pode ter que lidar com novas variáveis ​​adicionadas no MySQL 8.0. Por exemplo, essas variáveis ​​podem afetar seu servidor MySQL 8.0:
  • innodb_log_spin_cpu_abs_lwm =80
  • innodb_log_spin_cpu_pct_hwm =50
  • innodb_log_wait_for_flush_spin_hwm =400
  • innodb_parallel_read_threads =4

As variáveis ​​com seus valores são deixadas por seus valores padrão para este benchmark. As três primeiras variáveis ​​tratam da CPU para redo logging, que no MySQL 8.0 foi uma melhoria devido ao redesenho de como o InnoDB grava no log REDO. A variável innodb_log_spin_cpu_pct_hwm tem afinidade de CPU, o que significa que ela ignoraria outros núcleos de CPU se o mysqld estiver fixado em apenas 4 núcleos, por exemplo. Para threads de leitura paralela, no MySQL 8.0, ele adiciona uma nova variável para a qual você pode ajustar quantos threads serão usados.

No entanto, não me aprofundei no assunto. Pode haver maneiras de melhorar o desempenho aproveitando os recursos que o MySQL 8.0 tem a oferecer.

Conclusão


Há toneladas de melhorias que estão presentes no MySQL 8.0. Os resultados do benchmark revelam que houve uma melhoria impressionante, não apenas no gerenciamento de cargas de trabalho de leitura, mas também em uma alta carga de trabalho de leitura/gravação em comparação com o MySQL 5.7.

Passando para os novos recursos do MySQL 8.0, parece que ele aproveitou as tecnologias mais atualizadas não apenas em software (como grande melhoria para Memcached, gerenciamento remoto para melhor trabalho de DevOps, etc.), mas também em hardware. Por exemplo, a substituição de latin1 por UTF8MB4 como a codificação de caracteres padrão. Isso significaria que seria necessário mais espaço em disco, pois o UTF8 precisa de 2 bytes nos caracteres não-US-ASCII. Embora esse benchmark não tenha aproveitado o uso do novo método de autenticação com caching_sha2_password, ele não afetará o desempenho se ele usar criptografia. Uma vez autenticado, ele é armazenado em cache, o que significa que a autenticação é feita apenas uma vez. Portanto, se você estiver usando um usuário para seu cliente, não será um problema e será mais seguro que as versões anteriores.

Como o MySQL utiliza o hardware e software mais atualizados, ele altera suas variáveis ​​padrão. Você pode ler aqui para mais detalhes.

No geral, o MySQL 8.0 dominou o MySQL 5.7 de forma eficiente.