Estou trabalhando em um aplicativo que envolve muitas gravações de banco de dados, aproximadamente ~ 70% inserções e 30% leituras. Essa proporção também incluiria atualizações que considero uma leitura e uma gravação. Através de instruções de inserção, vários clientes inserem dados no banco de dados através da instrução de inserção abaixo:
$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");
A questão é se devo usar o insert_delay ou o mecanismo mysqli_multi_query porque a instrução insert utiliza ~ 100% da CPU no servidor. Estou usando o mecanismo InnoDB no meu banco de dados, portanto, a inserção com atraso não é possível. A inserção no servidor é ~ 36k / h e 99,89% de leitura, também estou usando a instrução select, recupera os dados sete vezes em uma única consulta , essa consulta leva 150 segundos no servidor para executar. Que tipo de técnica ou mecanismo posso usar para esta tarefa? A memória do meu servidor é de 2 GB, devo expandir a memória ?. Dê uma olhada neste problema, qualquer sugestão será grata a mim.
Estrutura da tabela:
+-----------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(100) | NO | | NULL | |
| uniq_name | varchar(200) | NO | | NULL | |
| ad_name | varchar(200) | NO | | NULL | |
| ad_delay_time | int(11) | NO | | NULL | |
| track_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+-----------------+--------------+------+-----+-------------------+----------------+
O status atual do meu banco de dados mostra 41k inserções (gravações), o que é muito lento para o meu banco de dados.
SHOW FULL PROCESSLIST
quando estiver usando 100% da CPU? Quantas conexões você está permitindo e quantas são feitas durante esse período?SHOW GLOBAL VARIABLES LIKE 'innodb%';
eSELECT VERSION();
e exibir sua saída.Respostas:
Como você tem mais gravações do que leituras, gostaria de recomendar o seguinte
O ajuste decente do InnoDB seria a chave
Buffer Pool (dimensionado por innodb_buffer_pool_size )
Como o InnoDB não suporta INSERT DELAYED , o uso de um grande buffer pool do InnoDB é a coisa mais próxima que você pode obter de INSERT DELAYED. Todos os DML (INSERTs, UPDATEs e DELETEs) seriam armazenados em cache no buffer pool do InnoDB. As informações transacionais para as gravações são gravadas imediatamente nos refazer logs (ib_logfile0, ib_logfile1). As gravações postadas no Buffer Pool são periodicamente descarregadas da memória para o disco via ibdata1 (InsertBuffer para índices secundários, buffer de gravação dupla). Quanto maior o pool de buffers, maior a quantidade de INSERTs que podem ser armazenados em cache. Em um sistema com 8 GB ou mais de RAM, use 75-80% da RAM como tamanho innodb_buffer_pool_spool. Em um sistema com muito pouca RAM, 25% (para acomodar o sistema operacional).
CAVEAT: você pode definir innodb_doublewrite como 0 para acelerar ainda mais as gravações, mas com o risco de integridade dos dados. Você também pode acelerar as coisas configurando innodb_flush_method como O_DIRECT para impedir o cache do InnoDB no sistema operacional.
Refazer logs (dimensionado por innodb_log_file_size )
Por padrão, os logs de refazer são denominados ib_logfile0 e ib_logfile1 e teriam 5 MB cada. O tamanho deve ser 25% do tamanho innodb_buffer_pool_spool. Se os logs de refazer já existirem, adicione a nova configuração no my.cnf, encerre o mysql, exclua-os e reinicie o mysql .
Buffer de log (dimensionado por innodb_log_buffer_size )
O buffer de log retém as alterações na RAM antes de liberá-las nos logs de refazer. O padrão é 8M. Quanto maior o buffer de log, menor a E / S de disco. Tenha cuidado com transações muito grandes, pois isso pode diminuir os COMMITs em milissegundos.
Acessando várias CPUs
O MySQL 5.5 e o MySQL 5.1 InnoDB Plugin têm configurações para que o InnoDB Storage Engine acesse várias CPUs. Aqui estão as opções que você precisa definir:
Atualize para o MySQL 5.5
Se você possui o MySQL 5.0, atualize para o MySQL 5.5. Se você possui o MySQL 5.1.37 ou anterior, atualize para o MySQL 5.5. Se você possui o MySQL 5.1.38 ou superior e deseja permanecer no MySQL 5.1, instale o plug-in InnoDB. Dessa forma, você pode tirar proveito de todas as CPUs do InnoDB.
fonte
INT (2) ainda usa 4 bytes - talvez você quis dizer TINYINT UNSIGNED?
Quantos valores diferentes em setno? Se for pequeno, o KEY (setno) nunca será usado. INSERTing precisa atualizar esse índice; remover a tecla acelerará a inserção de alguns.
CHAR (10) -
flag
Sempre tem 10 caracteres? E no utf8? Talvez você possa usar o sinalizador VARCHAR (10) CHARACTER SET asciiLote suas inserções - 100 de cada vez serão executadas 10 vezes mais rápido. (Mais de 100 está entrando em 'retornos decrescentes'.)
Qual é o valor da confirmação automática? Você está agrupando cada INSERT em BEGIN ... COMMIT? Qual é o valor de innodb_flush_log_at_trx_commit?
fonte
code
inserir em t_name (col1, col2, col3) valores (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3);code
Configure uma fila. O aplicativo gravaria uma fila 1 linha por vez e, em seguida, retiraria as linhas e as inseria em um banco de dados em lote com base no número de linhas da quantidade de tempo passado desde a última inserção.
Vi onde o lote das pastilhas 10.000 de cada vez é o mais rápido, então você precisaria testar para encontrar um ponto ideal.
Você pode criar seu próprio sistema de filas simples ou usar um existente. Aqui estão alguns exemplos: HornetQ e File :: Queue . Aqui está um post no SE listando outras boas opções: Filas de mensagens em perl, php, python .
fonte