Использование MySQL 5.6 с механизмом хранения InnoDB для большинства таблиц. Размер пула буферов InnoDB составляет 15 ГБ, а индексы Innodb DB + - около 10 ГБ. Сервер имеет 32 ГБ оперативной памяти и работает под управлением Cent OS 7 x64.
У меня есть одна большая таблица, которая содержит около 10 миллионов записей.
Я получаю обновленный файл дампа с удаленного сервера каждые 24 часа. Файл в формате CSV. У меня нет контроля над этим форматом. Файл ~ 750 МБ. Я попытался вставить данные в таблицу MyISAM строка за строкой, и это заняло 35 минут.
Мне нужно взять только 3 значения на строку из 10-12 из файла и обновить его в базе данных.
Какой лучший способ добиться чего-то подобного?
Мне нужно делать это ежедневно.
В настоящее время поток выглядит так:
- mysqli_begin_transaction
- Читать файл дампа построчно
- Обновляйте каждую запись построчно.
- mysqli_commit
Вышеуказанные операции занимают около 30-40 минут, и при этом происходят другие обновления, которые дают мне
Превышено время ожидания блокировки; попробуйте перезапустить транзакцию
Обновление 1
загрузка данных в новую таблицу с использованием LOAD DATA LOCAL INFILE. В MyISAM это заняло, 38.93 secа в InnoDB - 7 минут 5,21 секунды. Тогда я сделал:
UPDATE table1 t1, table2 t2
SET
t1.field1 = t2.field1,
t1.field2 = t2.field2,
t1.field3 = t2.field3
WHERE t1.field10 = t2.field10
Query OK, 434914 rows affected (22 hours 14 min 47.55 sec)
Обновление 2
то же самое обновление с запросом соединения
UPDATE table1 a JOIN table2 b
ON a.field1 = b.field1
SET
a.field2 = b.field2,
a.field3 = b.field3,
a.field4 = b.field4
(14 hours 56 min 46.85 sec)
Разъяснения по вопросам в комментариях:
- Приблизительно 6% строк в таблице будут обновлены файлом, но иногда это может достигать 25%.
- Есть указатели на обновляемые поля. В таблице 12 индексов, и 8 индексов содержат поля обновления.
- Нет необходимости делать обновление за одну транзакцию. Это может занять время, но не более 24 часов. Я хочу сделать это за 1 час, не блокируя всю таблицу, так как позже мне придется обновить индекс сфинкса, который зависит от этой таблицы. Неважно, если эти шаги занимают больше времени, если база данных доступна для других задач.
- Я мог бы изменить формат CSV на этапе предварительной обработки. Единственное, что имеет значение, это быстрое обновление и без блокировки.
- Таблица 2 - MyISAM. Это вновь созданная таблица из CSV-файла с использованием данных загрузки данных. Размер файла MYI составляет 452 МБ. Таблица 2 индексируется в столбце field1.
- MYD таблицы MyISAM составляет 663 МБ.
Обновление 3:
здесь более подробно об обеих таблицах.
CREATE TABLE `content` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`og_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`keywords` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`files_count` smallint(5) unsigned NOT NULL DEFAULT '0',
`more_files` smallint(5) unsigned NOT NULL DEFAULT '0',
`files` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`category` smallint(3) unsigned NOT NULL DEFAULT '600',
`size` bigint(19) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) NOT NULL DEFAULT '0',
`completed` int(11) NOT NULL DEFAULT '0',
`uploaders` int(11) NOT NULL DEFAULT '0',
`creation_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`upload_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`vote_up` int(11) unsigned NOT NULL DEFAULT '0',
`vote_down` int(11) unsigned NOT NULL DEFAULT '0',
`comments_count` int(11) NOT NULL DEFAULT '0',
`imdb` int(8) unsigned NOT NULL DEFAULT '0',
`video_sample` tinyint(1) NOT NULL DEFAULT '0',
`video_quality` tinyint(2) NOT NULL DEFAULT '0',
`audio_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`subtitle_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`uploader` int(11) unsigned NOT NULL DEFAULT '0',
`anonymous` tinyint(1) NOT NULL DEFAULT '0',
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`tfile_size` int(11) unsigned NOT NULL DEFAULT '0',
`scrape_source` tinyint(1) unsigned NOT NULL DEFAULT '0',
`record_num` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`record_num`),
UNIQUE KEY `hash` (`hash`),
KEY `uploaders` (`uploaders`),
KEY `tfile_size` (`tfile_size`),
KEY `enabled_category_upload_date_verified_` (`enabled`,`category`,`upload_date`,`verified`),
KEY `enabled_upload_date_verified_` (`enabled`,`upload_date`,`verified`),
KEY `enabled_category_verified_` (`enabled`,`category`,`verified`),
KEY `enabled_verified_` (`enabled`,`verified`),
KEY `enabled_uploader_` (`enabled`,`uploader`),
KEY `anonymous_uploader_` (`anonymous`,`uploader`),
KEY `enabled_uploaders_upload_date_` (`enabled`,`uploaders`,`upload_date`),
KEY `enabled_verified_category` (`enabled`,`verified`,`category`),
KEY `verified_enabled_category` (`verified`,`enabled`,`category`)
) ENGINE=InnoDB AUTO_INCREMENT=7551163 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED
CREATE TABLE `content_csv_dump_temp` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`category_id` int(11) unsigned NOT NULL DEFAULT '0',
`uploaders` int(11) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) unsigned NOT NULL DEFAULT '0',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
и вот запрос на обновление, который обновляет contentтаблицу, используя данные изcontent_csv_dump_temp
UPDATE content a JOIN content_csv_dump_temp b
ON a.hash = b.hash
SET
a.uploaders = b.uploaders,
a.downloaders = b.downloaders,
a.verified = b.verified
обновление 4:
Все вышеперечисленное тестирование проводилось на тестовой машине, но теперь я провел те же тесты на рабочей машине, и запросы выполнялись очень быстро.
mysql> UPDATE content_test a JOIN content_csv_dump_temp b
-> ON a.hash = b.hash
-> SET
-> a.uploaders = b.uploaders,
-> a.downloaders = b.downloaders,
-> a.verified = b.verified;
Query OK, 2673528 rows affected (7 min 50.42 sec)
Rows matched: 7044818 Changed: 2673528 Warnings: 0
Я прошу прощения за свою ошибку. Лучше использовать объединение вместо каждого обновления записи. теперь я пытаюсь улучшить mpre, используя индекс, предложенный rick_james, обновлю его после того, как будет проведена оценка производительности.
UPDATEs . Пожалуйста, расскажите нам , как выглядит прямое утверждение для обновления таблицы из данных CSV. Тогда мы сможем помочь вам разработать технику, которая соответствует вашим требованиям.
update, и, пожалуйста, проверьте обновленный вопрос. Спасибо
INDEX(field2, field3, field4)(в любом порядке)? Пожалуйста, покажите намSHOW CREATE TABLE.