Використання MySQL 5.6 з механізмом зберігання InnoDB для більшості таблиць. Розмір пулу буфера InnoDB становить 15 ГБ, а індекси Innodb DB + - близько 10 ГБ. Сервер має 32 Гб оперативної пам’яті та працює на Cent OS 7 x64.
У мене є одна велика таблиця, яка містить близько 10 мільйонів + записів.
Я отримую оновлений дамп-файл із віддаленого сервера кожні 24 години. Файл у форматі CSV. Я не маю контролю над цим форматом. Файл становить ~ 750 Мб. Я спробував вставити дані в таблицю MyISAM рядок за рядком, і це зайняло 35 хвилин.
Мені потрібно взяти з файлу лише 3 значення на рядок з 10-12 і оновити його в базі даних.
Який найкращий спосіб досягти подібного?
Мені це потрібно робити щодня.
В даний час Flow такий:
- 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 - 663MB.
Оновлення 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
.