Использование 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
.