Це запитання перенесено із програми переповнення стека на підставі пропозиції в коментарях, вибачень за дублювання.
Запитання
Питання 1: Коли розмір таблиці бази даних збільшується, як я можу настроїти MySQL, щоб збільшити швидкість виклику ЗАВАНТАЖЕННЯ ДАНИХ INFILE?
Запитання 2: чи використовує кластер комп'ютерів для завантаження різних файлів csv, покращить продуктивність чи знищить його? (це моє завдання по розмітці на лавці завтра з використанням даних про навантаження та об'ємних вставок)
Мета
Ми випробовуємо різні комбінації детекторів функцій та параметрів кластеризації для пошуку зображень, в результаті чого нам потрібно вчасно створювати та створювати великі бази даних.
Інформація про машину
Машина має 256 гіг оперативної пам’яті, і є ще 2 машини, доступні з такою ж кількістю оперативної пам’яті, якщо є спосіб покращити час створення шляхом розподілу бази даних?
Таблична схема
виглядає схема таблиці
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| match_index | int(10) unsigned | NO | PRI | NULL | |
| cluster_index | int(10) unsigned | NO | PRI | NULL | |
| id | int(11) | NO | PRI | NULL | auto_increment |
| tfidf | float | NO | | 0 | |
+---------------+------------------+------+-----+---------+----------------+
створений с
CREATE TABLE test
(
match_index INT UNSIGNED NOT NULL,
cluster_index INT UNSIGNED NOT NULL,
id INT NOT NULL AUTO_INCREMENT,
tfidf FLOAT NOT NULL DEFAULT 0,
UNIQUE KEY (id),
PRIMARY KEY(cluster_index,match_index,id)
)engine=innodb;
Бенчмаркінг поки що
Першим кроком було порівняння об'ємних вставок із завантаженням з двійкового файлу у порожню таблицю.
It took: 0:09:12.394571 to do 4,000 inserts with 5,000 rows per insert
It took: 0:03:11.368320 seconds to load 20,000,000 rows from a csv file
Зважаючи на різницю в продуктивності, я пішов із завантаженням даних з двійкового файлу csv, спочатку я завантажив двійкові файли, що містять рядки 100K, 1M, 20M, 200M, використовуючи виклик нижче.
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
Я знищив завантаження двійкового файлу 200M рядків (~ 3 Гб CSV-файл) через 2 години.
Тому я запустив сценарій для створення таблиці, і вставив різні числа рядків з двійкового файлу, а потім опустив таблицю, дивіться графік нижче.
Щоб вставити 1М рядків з двійкового файлу, знадобилося близько 7 секунд. Далі я вирішив заздалегідь встановити 1М рядків, щоб побачити, чи не буде вузького місця у певному розмірі бази даних. Як тільки база даних потрапила приблизно на 59М рядків, середній час вставки впав приблизно до 5000 / секунду
Встановлення глобального key_buffer_size = 4294967296 трохи покращило швидкість для вставки менших бінарних файлів. На графіку нижче показані швидкості для різної кількості рядків
Однак для вставки 1М рядків це не покращило продуктивність.
рядки: 1 000 000 часу: 0: 04: 13,761428 вставок / сек: 3,940
vs для порожньої бази даних
рядки: 1 000 000 часу: 0: 00: 6,339295 вставок / сек: 315,492
Оновлення
Виконання даних про завантаження за допомогою наступної послідовності проти просто використання команди даних про завантаження
SET autocommit=0;
SET foreign_key_checks=0;
SET unique_checks=0;
LOAD DATA INFILE '/mnt/imagesearch/tests/eggs.csv' INTO TABLE test_ClusterMatches;
SET foreign_key_checks=1;
SET unique_checks=1;
COMMIT;
Таким чином, це виглядає досить перспективно з точки зору розміру бази даних, який створюється, але інші параметри, здається, не впливають на ефективність завантаження даних для завантаження даних.
Потім я спробував завантажувати декілька файлів з різних машин, але команда завантаження даних infile блокує таблицю через великий розмір файлів, що призводить до того, що інші машини вичерпаються
ERROR 1205 (HY000) at line 1: Lock wait timeout exceeded; try restarting transaction
Збільшення кількості рядків у двійковому файлі
rows: 10,000,000 seconds rows: 0:01:36.545094 inserts/sec: 103578.541236
rows: 20,000,000 seconds rows: 0:03:14.230782 inserts/sec: 102970.29026
rows: 30,000,000 seconds rows: 0:05:07.792266 inserts/sec: 97468.3359978
rows: 40,000,000 seconds rows: 0:06:53.465898 inserts/sec: 96743.1659866
rows: 50,000,000 seconds rows: 0:08:48.721011 inserts/sec: 94567.8324859
rows: 60,000,000 seconds rows: 0:10:32.888930 inserts/sec: 94803.3646283
Рішення: Попередньо обчислити ідентифікатор за межами MySQL замість використання автоматичного збільшення
Побудова столу с
CREATE TABLE test (
match_index INT UNSIGNED NOT NULL,
cluster_index INT UNSIGNED NOT NULL,
id INT NOT NULL ,
tfidf FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY(cluster_index,match_index,id)
)engine=innodb;
з SQL
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
Отримання сценарію для попереднього обчислення індексів, здається, видалило показник продуктивності, оскільки база даних збільшується в розмірах.
Оновлення 2 - за допомогою таблиць пам'яті
Приблизно в 3 рази швидше, не враховуючи витрат на переміщення таблиці в пам'яті до таблиці на основі диска.
rows: 0 seconds rows: 0:00:26.661321 inserts/sec: 375075.18851
rows: 10000000 time: 0:00:32.765095 inserts/sec: 305202.83857
rows: 20000000 time: 0:00:38.937946 inserts/sec: 256818.888187
rows: 30000000 time: 0:00:35.170084 inserts/sec: 284332.559456
rows: 40000000 time: 0:00:33.371274 inserts/sec: 299658.922222
rows: 50000000 time: 0:00:39.396904 inserts/sec: 253827.051994
rows: 60000000 time: 0:00:37.719409 inserts/sec: 265115.500617
rows: 70000000 time: 0:00:32.993904 inserts/sec: 303086.291334
rows: 80000000 time: 0:00:33.818471 inserts/sec: 295696.396209
rows: 90000000 time: 0:00:33.534934 inserts/sec: 298196.501594
завантаживши дані в таблицю на основі пам'яті, а потім скопіювавши її в таблицю на основі диска, шматки мали накладні витрати 10 хв 59,71 сек для копіювання 107 356 741 рядків із запитом
insert into test Select * from test2;
що дозволяє приблизно 15 хвилин завантажувати 100М рядків, що приблизно те саме, що безпосередньо вставляти його в таблицю на основі диска.
id
слід швидше. (Хоча я думаю, ви цього не шукаєте)