As inserções na tabela a seguir estão demorando até 70 segundos para serem concluídas:
CREATE TABLE IF NOT EXISTS `productsCategories` (
`categoriesId` int(11) NOT NULL,
`productsId` int(11) NOT NULL,
PRIMARY KEY (`categoriesId`,`productsId`),
KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Existem cerca de 100.000 linhas na tabela, e está tomando 7 MB no disco.
Existem algumas configurações no MySQL que podem melhorar o desempenho da gravação?
Meu my.cnf
arquivo é o seguinte:
log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1
log-queries-not-using-indexes
innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT
query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800
sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
read_buffer_size=128K
open_files_limit = 1000
table_definition_cache = 1024
table_open_cache = 6000
max_heap_table_size=512M
tmp_table_size=4096M
max_connections=1000
thread_concurrency = 24
Aqui está a configuração do hardware:
- Dell R710
- RAID10
- 48G RAM
Dado esse hardware, eu não esperaria que o problema fosse um gargalo de hardware.
Respostas:
OBSERVAÇÃO Nº 1
A primeira coisa que chama minha atenção é a estrutura da mesa
Observe que o
categoriesId
índice e a PRIMARY KEY começam com a mesma coluna. É um índice redundante. Como esta tabela é InnoDB, ocategoriesId
índice é redundante por outro motivo: Todos os índices secundários contêm chaves em gen_clust_index (também conhecido como Índice Clusterizado; Veja para que é usado gen_clust_index no mysql? )Se você remover o
categoriesId
índice comisso melhorará drasticamente os INSERTs porque não é necessário fazer manutenção extra de índice secundário e em cluster.
OBSERVAÇÃO Nº 2
Se você estiver executando alguma operação de inserção em massa, precisará de um buffer grande de inserção em massa .
Por favor, veja minhas postagens anteriores sobre isso:
OBSERVAÇÃO Nº 3
O tamanho do seu arquivo de log é muito pequeno !!! Deve ser 25% do InnoDB Buffer Pool, que no seu caso deve ser 1G. Veja meu post sobre como redimensionar arquivos de log do InnoDB .
OBSERVAÇÃO Nº 4
Por favor, não defina innodb_thread_concurrency !!! Aprendi em primeira mão no Percona Live NYC a deixar esse cenário em paz . Ele está desativado por padrão no MySQL 5.5, MySQL 5.1 InnoDB Plugin e Percona Server 5.1 ou superior.
OBSERVAÇÃO Nº 5
Você precisa usar innodb_file_per_table. Se isso estiver desativado, tornarei a manutenção de arquivos no ibdata1 um pesadelo. Leia meu post sobre como limpar o InnoDB para implementar isso .
OBSERVAÇÃO Nº 6
Se você estiver usando o MySQL 5.5 ou o Percona Server, precisará definir certas opções para fazer com que o InnoDB use CPUs múltiplas / múltiplos núcleos. Por favor, veja o meu post sobre essas configurações .
OBSERVAÇÃO Nº 7
Você tem
innodb_log_buffer_size=4M
. O padrão é 8M. Isso causará o dobro de descarga nos logs de refazer. Isso também irá neutralizar suainnodb_flush_log_at_trx_commit=2
configuração. Defina-o para 32 milhões. Além disso, consulte a documentação do MySQL em innodb_log_buffer_size .À luz dessas observações, adicione ou substitua as seguintes configurações:
fonte
query_cache_size
é enorme também. Cada inserção exigirá a liberação de até 6 GB de cache.Você deve verificar
innodb_log_file_size
, a configuração padrão é 5M, que é bastante baixa para configurações intensivas de gravação. Considere configurá-lo para 100M. Você precisará excluir osib_logfile*
arquivos antigos para iniciar o banco de dados com novas configurações. Por favor, não exclua os arquivos de log enquanto o servidor de banco de dados estiver em execução; será necessário interrompê-lo primeiro. Provavelmente você deve primeiro fazer backup dos arquivos de log antigos, não apenas excluí-los.fonte