mysql займає занадто багато часу для надсилання даних


9

У мене проста таблиця з мільйонами записів (14 000 000), і для простого запиту витрачається занадто багато часу на "пересилання даних".

Стіл

CREATE TABLE IF NOT EXISTS details (
  id int(11) NOT NULL,
  date date NOT NULL,
  time int(2) NOT NULL,
  minutes_online decimal(5,0) NOT NULL,
  minutes_playing decimal(5,0) NOT NULL,
  minutes_chatting decimal(5,0) NOT NULL,
  minutes_away decimal(5,0) NOT NULL
  PRIMARY KEY (id,date,time)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Простий запит

mysql> SELECT * FROM details WHERE id = 3014595;

Поясніть

mysql> EXPLAIN SELECT * FROM details WHERE id = 3014595;
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | details   | ref  | PRIMARY       | PRIMARY | 4       | const | 1482 |       |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+

Профіль для запиту

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000024 |
| checking query cache for query | 0.000078 |
| checking permissions           | 0.000014 |
| Opening tables                 | 0.000126 |
| System lock                    | 0.000011 |
| Table lock                     | 0.000030 |
| init                           | 0.000027 |
| optimizing                     | 0.000117 |
| statistics                     | 0.040077 |
| preparing                      | 0.000029 |
| executing                      | 0.000006 |
| Sending data                   | 7.536960 |
| end                            | 0.000013 |
| query end                      | 0.000004 |
| freeing items                  | 0.000037 |
| storing result in query cache  | 0.000006 |
| logging slow query             | 0.000003 |
| cleaning up                    | 0.000006 |
+--------------------------------+----------+

Як бачимо, в SELECTоператорі використовували індекс і читали лише 1482 рядки. Тим не менш, запит витратив 7,536960 секунд на надсилання даних. Це як запит, який читає набагато більше рядків, які йому потрібні.

Це простий запит, що має лише 7 полів (рядок середнього рівня 59 байт) і не має фантазійних функцій. Будь-яка ідея, що може бути причиною цього?

Примітка: id - ідентифікатор користувача. Кожен користувач може мати принаймні один запис на кожну годину кожного дня. Тому ідентифікатор не є унікальним.

Редагувати: У мене є ще одна таблиця з такою ж структурою і набагато більше рядків (34 мільйони). Якщо я запускаю той самий запит у цій великій таблиці, він повертає результати менше ніж за 1 секунду.

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

  • Чи можливо кількість запитів уповільнює процес? Кеш MySQL увімкнено. Я також кешував кешування запитів, щоб зменшити кількість запитів.
  • Можливо, файл, де збережена таблиця, пошкоджений чи щось?

Оновлення Проблему було вирішено шляхом відокремлення рівня даних від веб-рівня. Рівень даних також отримав оновлення оперативної пам’яті та працює на raid10.


Скільки рядків SELECTповертається?
hjpotter92

1591 rows in set (16.48 sec)Я знову запустив запит, тому тривалість різна. Зараз
минуло

замість * намагайтеся використовувати стовпці, а потім подивіться, яка різниця це робить
Мухаммад Рахіль

Ні. Той самий результат.
rlcabral

Спробуйте зробити стовпчик ідентифікатора простим первинним індексом. Оскільки ID повинен бути унікальним полем, вам не потрібно робити складні індекси з ним. Це має зробити ваш пошук за первинним ключем швидким, як світлодіодний.
Олександр Правдін

Відповіді:


1

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

https://dev.mysql.com/doc/refman/5.7/uk/general-thread-states.html

Потік читає та обробляє рядки для оператора SELECT та надсилає дані клієнту. Оскільки операції, що відбуваються під час цього стану, мають тенденцію до отримання великого обсягу доступу до диска (читання), часто це стан, який працює найдовше протягом життя певного запиту.


-2

Спробуйте Оптимізувати таблицю за допомогою Оптимізувати ім'я таблиці таблиці та перевірити стан.

Великі зміни потрібно зробити:

Alter table tablename engine = 'INNODB'

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


-3

Створіть окремий індекс для id:

змінити деталі таблиці, додати ключ d1 (id);

Щоб скористатися цим індексом, перезапустіть MySQL або

проаналізувати деталі таблиці;

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


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