Як використовувати затримку вставки з двигуном InnoDB і використовувати менше з'єднання для операторів вставки?


10

Я працюю над додатком, який включає багато записів у базу даних, приблизно ~ 70% вставок і 30% читає. Це співвідношення також включатиме оновлення, які я вважаю одним читанням та одним записом. Через оператори вставлення кілька клієнтів вставляють дані в базу даних через оператор insert нижче:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

Питання в тому, чи слід використовувати або insert_delay, або використовувати механізм mysqli_multi_query, оскільки оператор insert використовує ~ 100% процесора на сервері. Я використовую двигун InnoDB у своїй базі даних, тож вставити затримку неможливо. Вставлення на сервері становить ~ 36 к / год і 99,89% прочитаного, також я використовую оператор select, там вилучаю дані сім разів за один запит , на виконання цього запиту на сервері потрібно 150 секунд. Яку техніку чи механізм я можу використовувати для цього завдання? Моя пам'ять сервера - 2 Гб, чи слід розширювати пам'ять ?. Погляньте на цю проблему, будь-яка пропозиція буде мені вдячна.

Структура таблиці:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

У моїй базі даних теперішній статус, він показує 41k вставки (записи), що дуже повільно для моєї бази даних.

стан бази даних


Чи можете ви надати визначення таблиці? (усі стовпці, типи даних та індекси)
ypercubeᵀᴹ

Чи можете ви дати короткий фрагмент свого, SHOW FULL PROCESSLISTколи він займає 100% процесор? Скільки з'єднань ви дозволяєте порівняно з кількістю знятих за цей час?
Дерек Дауні

Будь ласка , запустіть ці два запити: SHOW GLOBAL VARIABLES LIKE 'innodb%';і SELECT VERSION();та відображати їх висновок.
RolandoMySQLDBA

Будь ласка, вкажіть кількість вставок, які ви виконуєте.
dabest1

Ваш код дуже чутливий до ін'єкції SQL. Використовуйте підготовлені оператори та параметризовані значення.
Аарон Браун

Відповіді:


12

Оскільки у вас є більше записів, то читається, я хотів би порекомендувати наступне

Гідна настройка InnoDB була б ключовою

Буферний басейн ( розмір innodb_buffer_pool_size )

Оскільки InnoDB не підтримує INSERT DELAYED , використання великого пулу InnoDB Buffer є найближчою справою, яку можна дістати до INSERT DELAYED. Усі DML (INSERT, UPDATE і DELETE) будуть кешовані в пулі InnoDB. Інформація про трансакцію для Writes записується негайно до журналів Redo (ib_logfile0, ib_logfile1). Записи, розміщені в буферному пулі, періодично передаються з пам'яті на диск через ibdata1 (InsertBuffer для вторинних індексів, подвійний буфер запису). Чим більше буферний пул, тим більша кількість ВСТАНОВЛЕНЬ можна кешувати. У системі з 8 Гб або більше оперативної пам’яті використовуйте 75-80% оперативної пам’яті як розмір innodb_buffer_pool_size. У системі з дуже малою ОЗУ, 25% (для розміщення ОС).

CAVEAT: Ви можете встановити innodb_doublewrite на 0, щоб пришвидшити написання ще більше, але загрожує цілісність даних. Ви також можете прискорити роботу, встановивши innodb_flush_method на O_DIRECT, щоб запобігти кешування InnoDB в ОС.

Повторити журнали ( розмір innodb_log_file_size )

За замовчуванням повторні журнали мають ім’я ib_logfile0 та ib_logfile1 і становитимуть 5 Мб кожен. Розмір повинен бути 25% від величини innodb_buffer_pool_size. Якщо журнали повторень вже існують, додайте нове налаштування в my.cnf, закрийте mysql, видаліть їх та перезапустіть mysql .

Буфер журналу ( розмір innodb_log_buffer_size )

Буфер журналу зберігає зміни в оперативній пам'яті перед тим, як передати їх у повторені журнали. За замовчуванням - 8М. Чим більший буфер журналу, тим менше дискового вводу / виводу. Будьте обережні при дуже великих транзакціях, оскільки це може уповільнити COMMIT на мілісекунди.

Доступ до декількох процесорів

MySQL 5.5 та MySQL 5.1 InnoDB Plugin мають налаштування для доступу InnoDB Storage Engine до декількох процесорів. Ось варіанти, які потрібно встановити:

  • innodb_thread_concurrency встановлює верхню межу для кількості одночасних потоків, які InnoDB може тримати відкритими. Зазвичай рекомендується встановити для цього (2 X Кількість процесорів) + Кількість дисків. Минулого року я з перших вуст дізнався на конференції Percona NYC, що вам слід встановити це значення 0, щоб попередити InnoDB Storage Engine, щоб знайти найкращу кількість потоків для середовища, в якому він працює.
  • innodb_concurrency_tickets встановлює кількість потоків, які можуть безкарно обійти перевірку сумісності . Після досягнення цієї межі перевірка сумісності потоку знову стає нормою.
  • innodb_commit_concurrency встановлює кількість одночасних транзакцій, які можуть бути здійснені. Оскільки за замовчуванням дорівнює 0, не встановлення цього параметра дозволяє одночасно здійснювати будь-яку кількість транзакцій.
  • innodb_thread_sleep_delay встановлює кількість мілісекунд, потік InnoDB може бути в режимі спокою перед повторним вводом черги InnoDB. За замовчуванням - 10000 (10 сек).
  • innodb_read_io_threads (встановіть це 3000) та innodb_write_io_threads (встановіть це 7000) (обидва з MySQL 5.1.38) виділяють вказану кількість потоків для читання та запису. За замовчуванням - 4, а максимум - 64. Установіть їх на 64. Також встановіть innodb_io_capacity на 10000.

Оновлення до MySQL 5.5

Якщо у вас MySQL 5.0, перейдіть до MySQL 5.5. Якщо у вас є MySQL 5.1.37 або раніше, оновіть до MySQL 5.5. Якщо у вас MySQL 5.1.38 або вище і хочете залишатися в MySQL 5.1, встановіть плагін InnoDB. Таким чином, ви можете скористатися всіма процесорами для InnoDB.


пам'ять мого сервера становить 2 Гб, тому відповідно до пам’яті я встановив пул буфера innodb на 500M, а файли журналів 25% для пулу, також встановіть буфер журналу в 64M. Але сервер все ще сильно зайнятий. Чи варто оновити пам'ять? Також мій сервер має 32-бітний ubuntu, так що макс я можу встановити пам'ять на 4 Гб.
Шашанк

Якщо сервер призначений лише для MySQL (немає апачу, не PHP), то innodb_buffer_pool_size може становити 75% від 2 Гб, що становить 1536 Мб. Якщо ви оновите до 4 Гб, innodb_buffer_pool_size може бути 3G. Файли журналу повинні становити 25% пулу буфера, як ви заявили.
RolandoMySQLDBA

Сервер працює під управлінням apache2, mysql та php, чи варто мені в цій ситуації перейти на оновлення пам’яті або є якесь оптимальне рішення, крім буфера пулу innodb?
Шашанк

Цей хлопець не згоден з вами: percona.com/blog/2008/11/21/… Важко сперечатися з Percona.
Zenexer

Роландо - пропоную вам додати відповідь із оновленнями для 5.6 та 5.7. Значення за замовчуванням змінилися; інші налаштування доступні; Можливо, включіть Percona та MariaDB та 8,0 підказки.
Рік Джеймс

2

INT (2) все ще використовує 4 байти - можливо, ви мали на увазі TINYINT UNSIGNED?

Скільки різних значень у setno? Якщо він невеликий, KEY (setno) ніколи не буде використовуватися. INSERTing має оновити цей індекс; видалення KEY пришвидшить ВСТАВИТИ деякі.

CHAR (10) - flagЗавжди 10 символів? А в utf8? Можливо, ви могли б використати прапор VARCHAR (10) CHARACTER SET ascii

Пакет своїх вставок - 100 одночасно працюватимуть в 10 разів швидше. (Понад 100 стає «зменшенням прибутку».)

Яке значення автокомісії? Ви загортаєте кожну ВСТАВку в ПОЧАТОК ... КОМІТ? Яке значення innodb_flush_log_at_trx_commit?


як я можу вставити пакет, якщо дані вставляються через зовнішнє джерело, як різні клієнти з різними значеннями .... чи надійно, якщо я використовую: codeвставте значення t_name (col1, col2, col3) (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3); code
Шашанк

1

Налаштування черги. Додаток записуватиметься у чергу 1 рядок за один раз, а потім витягуватиме рядки та вставлятиме в базу даних пакетною групою на основі кількості рядків, пройдених з моменту останньої вставки.

Я бачив, де партія вставок 10000 за один раз є найшвидшою, тому вам потрібно буде перевірити, щоб знайти солодке місце.

Ви можете створити власну просту систему черг або використовувати існуючу. Ось кілька прикладів: HornetQ та File :: Черга . Ось допис у SE, який містить деякі інші хороші варіанти: Черги повідомлень у perl, php, python .


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