Створення таблиці 1000 рядків MySQL


18

Це запитання перенесено із програми переповнення стека на підставі пропозиції в коментарях, вибачень за дублювання.

Запитання

Питання 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М рядків, що приблизно те саме, що безпосередньо вставляти його в таблицю на основі диска.


1
Я думаю, що змінити первинний ключ на просто idслід швидше. (Хоча я думаю, ви цього не шукаєте)
DavidEG

Привіт, Девід, дякую за коментар, на жаль, без ключових запитів, які нам потрібно зробити, недостатньо швидко (логіка вибору основного ключа викладена в цій публікації stackoverflow.com/questions/4282526/mysql-group-by- оптимізація )
Бен

1
Це тільки для тестування? Ви можете подивитися на двигун MySQL MEMORY: dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html Якщо ви плануєте розгорнути це як архітектуру, мені цікаво, як ви плануєте одужаючи від невдач, схоже на щось, з чим краще би впоралися MapReduce / Hadoop.
многочлен

Привіт поліном, спасибі за підказку, на даний момент ми просто тестуємо різні детектори функцій на різних масштабах, як тільки база даних буде сформована, вона звичайно не зміниться (у поточній специфікації все одно)
Ben

Відповіді:


4

Хороше запитання - добре пояснено.

як я можу настроїти MySQL, щоб збільшити швидкість виклику ЗАВАНТАЖЕННЯ ДАНИХ INFILE?

Ви вже отримали високу (ish) настройку для буфера ключів - але чи достатньо? Я припускаю, що це 64-бітна установка (якщо ні, то перше, що вам потрібно зробити, - це оновлення), а не запуск MSNT. Ознайомтеся з результатом mysqltuner.pl після запуску декількох тестів.

З метою використання кешу для найкращого ефекту, ви можете знайти переваги в групі / попередньому сортуванні вхідних даних (останні останні версії команди "сортувати" мають велику функціональність для сортування великих наборів даних). Крім того, якщо ви генеруєте ідентифікаційні номери поза MySQL, це може бути ефективнішим.

використовує кластер комп'ютерів для завантаження різних CSV-файлів

Якщо припустити (знову ж), що ви хочете, щоб набір вихідних даних поводився як одна таблиця, то єдині переваги, які ви отримаєте, - це розповсюдження роботи по сортуванню та генерації ідентифікаторів - для чого вам не потрібно більше баз даних. OTOH, використовуючи кластер бази даних, у вас виникнуть проблеми з суперечками (які ви не повинні бачити, крім як проблеми з продуктивністю).

Якщо ви зможете поділити дані та обробити отримані набори даних самостійно, то так, ви отримаєте переваги від продуктивності - але це не скасовує необхідності налаштування кожного вузла.

Перевірте, чи є у вас принаймні 4 Гбіт для сорту_буфер_розмір.

Крім того, обмежуючим фактором продуктивності є все, що стосується дискового вводу / виводу. Існує маса способів вирішити це питання, але ви, мабуть, повинні розглянути дзеркальний набір смугастих наборів даних на SSD для оптимальної роботи.


1
  • Розглянемо ваш обмежуючий фактор. Це майже напевно однопотокова обробка процесора.
  • Ви вже визначили, що load data...це швидше, ніж вставляти, тому використовуйте це.
  • Ви вже визначили, що дійсно великі файли (за номером рядка) значно сповільнюють роботу; ви хочете розбити їх на шматки.
  • Використовуючи первісні ключі, що не перекриваються, поставте в чергу не менше N * наборів процесора, використовуючи не більше одного мільйона рядків ... можливо, менше (орієнтир).
  • Використовуйте послідовні блоки первинних ключів у кожному файлі.

Якщо ви хочете бути по-справжньому хитрими, ви можете створити багатопотокову програму для подачі одного файлу в колекцію названих труб та керування екземплярами вставок.

Підсумовуючи, ви не налаштовуєте MySQL для цього настільки, як ви налаштовуєте своє навантаження на MySQL.


-1

Я точно не пам’ятаю синтаксис, але якщо це невірно, ви можете вимкнути перевірку зовнішнього ключа.

Також ви можете створити індекс після імпорту, це може бути справді збільшення продуктивності.


Відстрочення відновлення індексу лише покращує ефективність, коли кількість рядків, які вже є в таблиці, значно менша за кількість доданих рядків.
symcbean
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.