У меня есть следующая таблица соответствия:
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;
У меня есть таблица widgetuser_tmp с той же структурой, но без ключа, и я заполняю таблицу widgetuser этими данными (4 миллиона строк):
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)
Во время записи идет прямо к RAID-1 со скоростью 15 МБ / с, утилита диска
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
Я вставляю следующие 1 Mio-строки, все нормально, и wMB / s возвращается к 0 сразу после сброса:
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)
Но когда я делаю партию 7mio, результат все равно выглядит так же, но в iostat -mdx sda sdb 5
внезапно мы получаем 100% утилизации в течение 30 секунд:
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
После сброса файлы данных не затрагиваются:
-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
А также таблица состояния швов нормальная:
+----------------+--------+---------+------------+----------+----------------+-------------+-------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+-------------------+---------+
| 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 | |
+----------------+--------+---------+------------+----------+----------------+-------------+-------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+-------------------+---------+
И когда я продолжаю (так как у нас 100% загрузка диска), становится очень быстро:
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)
Первичный ключ проверяется, чтобы увидеть, является ли новая запись уникальной или нет. Как только ключ не помещается в память (key_buffer_size = 512MB = около 8 миллионов записей), ему необходимо извлечь недостающие ключевые части из накопителя (-cache) для проверки. Поэтому мы должны видеть больше операций чтения и медленного времени вставки - мы не видим медленных операций чтения, так как ключ буферизуется в кеше диска. Но мой вопрос: кто вдруг так много пишет и где и почему и как я могу это исправить? Любые идеи приветствуются!
Другие идеи и идеи:
- поскольку случайные записи со скоростью 1 МБ / с следуют за завершенным оператором, уникальная проверка уже пройдена
- это программный raid-1 с включенным ahci, диски свободны на 93% и способны работать на скорости около 80 ВтМБ / с
- машина имеет 8 ГБ оперативной памяти, 5 ГБ кэш-памяти, 600 МБ занято MySQL, 1,7 ГБ свободно
- MySQL 5.1.31-1ubuntu2-log
- delay_key_write не меняет это поведение
- myisam_sort_buffer_size = 2 ГБ (не используется здесь, хотя?)
- key_buffer_size = 512 МБ
- bin_log выключен
- Linux 2.6.28-15-сервер # 52-Ubuntu SMP Ср 9 сентября 11:34:09 UTC 2009 x86_64 GNU / Linux