Pergunta

Eu tenho o lookup-tabela a seguir:

CREATE TABLE `widgetuser` (
 `widgetuserid` char(40) NOT NULL,
 `userid` int(10) unsigned NOT NULL,
 `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 PRIMARY KEY (`widgetuserid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 DELAY_KEY_WRITE=1;

Eu tenho uma tabela widgetuser_tmp com a mesma estrutura, mas nenhuma tecla e eu preencher a tabela de widgetuser com esses dados (4mio linhas):

mysql> insert into widgetuser select * from widgetuser_tmp limit 0,4000000;flush tables;
Query OK, 4000000 rows affected (33.14 sec)
Records: 4000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (0.91 sec)

Embora seja escrita, ele vai diretamente para RAID-1 com 15MB / s, disco util <50% e não vemos lê, desde que eu preenchido o cache de disco com a tabela de origem:

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00  3839.20    0.00   52.40     0.00    15.20   594.20    12.46  237.75   5.57  29.20
sdb               0.00  3839.00    0.00   52.60     0.00    15.20   591.94    14.50  275.59   7.19  37.80

eu inserir os próximos 1 filas Mio, é tudo muito bem e o WMB / s remonta a 0 logo após o flush:

mysql> insert into widgetuser select * from widgetuser_tmp limit 4000000,1000000;flush tables;
Query OK, 1000000 rows affected (10.18 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (0.87 sec)

mysql> insert into widgetuser select * from widgetuser_tmp limit 5000000,1000000;flush tables;
Query OK, 1000000 rows affected (10.21 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (1.02 sec)

mysql> insert into widgetuser select * from widgetuser_tmp limit 6000000,1000000;flush tables;
Query OK, 1000000 rows affected (10.67 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (1.17 sec)

Mas quando eu faço o lote 7mio, o resultado ainda tem a mesma aparência, mas no iostat -mdx sda sdb 5 repente temos 100% util para 30 segundos:

mysql> insert into widgetuser select * from widgetuser_tmp limit 7000000,1000000;flush tables;
Query OK, 1000000 rows affected (10.73 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (1.21 sec)

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00    88.60    0.00  295.60     0.00     1.52    10.53   130.60  435.93   3.38 100.00
sdb               0.00    89.20    0.00  300.80     0.00     1.57    10.68   143.99  483.97   3.32 100.00

Os dados-arquivos não são tocados após o flush:

-rw-rw---- 1 mysql mysql 1032000000 2009-10-30 12:10 widgetuser.MYD
-rw-rw---- 1 mysql mysql  522777600 2009-10-30 12:11 widgetuser.MYI  

E também o status da tabela costuras normais:

+----------------+--------+---------+------------+----------+----------------+-------------+-------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+-------------------+---------+
| Name           | Engine | Version | Row_format | Rows     | Avg_row_length | Data_length | Max_data_length   | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options    | Comment |
+----------------+--------+---------+------------+----------+----------------+-------------+-------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+-------------------+---------+
| widgetuser     | MyISAM |      10 | Fixed      |  8000000 |            129 |  1032000000 | 36310271995674623 |    522777600 |         0 |           NULL | 2009-10-30 11:59:41 | 2009-10-30 12:10:59 | NULL       | utf8_general_ci |     NULL | delay_key_write=1 |         |
+----------------+--------+---------+------------+----------+----------------+-------------+-------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+-------------------+---------+

E quando eu continuar (uma vez que temos 100% de utilização da unidade), é obter do pior muito rápido:

mysql> insert into widgetuser select * from widgetuser_tmp limit 9000000,1000000;flush tables;
Query OK, 1000000 rows affected (31.93 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (2.34 sec)

mysql> insert into widgetuser select * from widgetuser_tmp limit 10000000,1000000;flush tables;
Query OK, 1000000 rows affected (2 min 39.72 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
Query OK, 0 rows affected (7.82 sec)

A chave primária é verificado para ver se a nova entrada é único ou não. Assim que a chave não caber na memória (key_buffer_size = 512 = ca. 8Mio entradas), ele precisa buscar as peças-chave ausente da unidade (-cache) para verificá-lo. Portanto, devemos ver mais leituras e mais lento inserção vezes - nós não vemos mais lento lê vez que a chave é tamponado no cache de disco. Mas a minha pergunta: que está escrevendo repente tanto e onde e por que e como posso corrigir isso? Todas as idéias são bem-vindas!

idéias Futher e insights:

  • desde gravações aleatórias a 1 MB / s seguir a declaração acabado, a validação única já é passado
  • é um software RAID-1 com ahci em diante, os discos são 93% livre e capaz de cerca de 80wMB / s
  • a máquina tem 8 GB de RAM, cache de 5GB, 600MB tomada pelo MySQL, 1,7GB livres
  • MySQL 5.1.31-1ubuntu2-log
  • o DELAY_KEY_WRITE não alterar esse comportamento
  • myisam_sort_buffer_size = 2 GB (não utilizado aqui, embora?)
  • key_buffer_size = 512 MB
  • bin_log é desligado
  • Linux 2.6.28-15-server # 52 Ubuntu SMP Wed 09 de setembro 11:34:09 UTC 2009 x86_64 GNU / Linux
Foi útil?

Solução

Não é inteiramente claro da sua pergunta o comportamento que você está esperando, ou recebendo. Aqui estão algumas coisas que você pode não saber

  • TABELAS FLUSH golpes afastado o cache de chaves MyISAM - não apenas escrever blocos de sujos, também as devoluções limpas assim que cada bloco de índice deve ser buscada novamente para ser modificado
  • MyISAM usa um tamanho de bloco de 1k por padrão que é provavelmente menor do que seus blocos de sistemas de arquivos; isso pode criar problemas de desempenho
  • Se você pretende qualquer tipo de durabilidade (que você provavelmente não, porque você está usando MyISAM), então você deve usar hardware RAID com um cache de bateria no controlador.

Meu palpite é que tanto o índice já não se encaixa no buffer de chave, ou que é ter que fazer muito mais gravações, que gatilho lê porque eles são gravações sem buffer fora dos limites do bloco de tamanho.

Tente alterar myisam_block_size de 4k ou mais e reconstruir a mesa (esta é uma opção de somente my.cnf que só entra em vigor em novas tabelas após a reinicialização).

Você pode examinar o tamanho do bloco em uma tabela com myisamchk -dv

Outras dicas

Estou usando mariadb5528, se o uso de key_buffer_size> 90%, parece que DELAY_KEY_WRITE não funcionam assim ampliar o key_buffer_size de 2G.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top