MySQL очень медленный на очень простых запросах SELECT

10

У нас есть простое веб-приложение, работающее на виртуальной машине, которое сохраняет свои данные в базе данных MySQL 5.5 с движком InnoDB. Все работало нормально около трех лет, но вдруг стало очень медленно.

Например, у меня есть очень простая таблица с адресами:

CREATE TABLE `addresses` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET latin1 NOT NULL,
  `firstname` varchar(64) CHARACTER SET latin1 NOT NULL,
  `street` varchar(64) CHARACTER SET latin1 NOT NULL,
  `housenumber` varchar(16) CHARACTER SET latin1 NOT NULL,
  `zip` varchar(5) CHARACTER SET latin1 NOT NULL,
  `city` varchar(64) CHARACTER SET latin1 NOT NULL,
  `email` varchar(64) CHARACTER SET latin1 NOT NULL,
  `phone` varchar(16) CHARACTER SET latin1 NOT NULL,
  `birthdate` date NOT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

Эта таблица содержит около 800 записей, что на самом деле не так много. Но выполнение запроса

SELECT * FROM addresses

в тестовых целях, кажется, никогда не закончить. Я проверил это с помощью CLI mysql на самом сервере: он выводит некоторые строки таблицы, а затем очень долго ждет, пока не выведет следующие строки.

Так что, возможно, это проблема на этапе отправки данных, но я не уверен.

ВМ имеет 2 ГБ оперативной памяти и используется только 320 МБ. Процессор также работает на очень низком уровне от 1 до 2%. mytop не показывает никаких других запросов, которые блокируют сервер. ИТ-администратор сказал, что они ничего не изменили в аппаратной части.

Я уже пробовал что-то вроде перезапуска сервера базы данных, перезапуска виртуальной машины. Ничего не помогло

редактировать:

EXPLAIN SELECT * FROM addresses

дает мне этот результат:

+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | addresses | ALL  | NULL          | NULL | NULL    | NULL |  793 |       |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
Tabb
источник
Виртуальная коробка, Xen или что-то еще? Как настроен диск хоста? есть ли другие виртуальные машины на том же компьютере, которые работают медленно? Ответ на эти вопросы может раскрыть ответ
Мэтт
Я не владелец гипервизора, поэтому я не могу ответить на этот вопрос. Я уже спросил администратора гипервизора, знают ли они о каких-либо недавних изменениях, но он сказал нет.
Табб
если можете, выключите mysql и запустите тест производительности диска и памяти. Не должно быть сложным. Идея состоит в том, чтобы просто изолировать, если это проблема с MySQL, возможно, проблема индекса, как указано в ответе ниже, или более распространенная.
Мэтт
Хороший вопрос, я испытал это, вероятно, не будучи проблемой mysql. Запуск mysql -u username -ppassword mydb -e 'SELECT * FROM addressesвыводится медленно, но, добавляя `> test.txt`, он работает очень быстро. Теперь это, наверное, другой вопрос !? Как я мог расследовать это?
Табб
Свяжитесь с владельцем гипервизора и попросите его проверить журналы на наличие ошибок. Конкретно дисковые ошибки. Скажите ему ваши симптомы. Резервное копирование сейчас.
Мэтт

Ответы:

13

Если загрузка процессора низкая, это указывает на отсутствие проблем с отсутствующими индексами, если бы это было так, запросу просто потребовалось бы больше процессора и доступа к диску. Также вы сказали, что он работал в течение 3 лет.

Проверяли ли вы общую скорость доступа к диску (особенно в разделе, где расположена база данных)? Например, используя dd как здесь . То, что вы описываете, звучит как мертвый диск или полумертвый рейд. Надеюсь, у меня есть резервные копии?

user3648611
источник
Неплохо подмечено. Это может быть что-то простое, например, ошибка диска на хосте.
Мэтт
9

Вы можете попробовать пару вещей,

  1. У вас есть настройки индексов?

Индексирование позволяет быстро находить записи без предварительного полного сканирования таблицы, значительно сокращая время выполнения.

CREATE INDEX idx_name ON addresses(name);
  1. Перед выполнением запроса сначала используйте ключевое слово EXPLAIN,

Когда он используется перед запросом SELECT, он описывает, как MySQL намеревается выполнить запрос, и количество строк, которые ему необходимо обработать, прежде чем он завершится.

  1. Внесите некоторые изменения в свой mysql.ini, если его виртуальная машина увеличит объем оперативной памяти, и настройте свой mysql.ini, чтобы увидеть, увеличивается ли производительность.

Существует множество оптимизаторов MySQL, которые могут вам помочь.

Помогите это поможет

Энтони Форнито
источник
Хорошо, но создание индекса для довольно маленькой таблицы (<800 строк) не так полезно, как мне бы того хотелось. Завершение запроса, указанного выше, занимает более минуты. Полное сканирование такого маленького стола не займет так много времени.
Табб
Итак ... вы добавили индексы? Если вы не уверены, в чем проблема, я начну с базового и продолжу свой путь вниз. Добавление индексов только увеличит производительность, если все сделано правильно.
Энтони Форнито
Да, я добавил индекс в столбце имени. Но мой вышеупомянутый запрос даже не имеет ограничивающего предложения WHERE, поэтому ему придется прочитать всю таблицу и распечатать ее. Добавленный индекс не помог.
Табб
Я добавил результат запроса EXPLAIN выше. Это выглядит хорошо для меня, но производительность все еще очень низка. Я не могу увеличить оперативную память, так как я не являюсь администратором менеджера виртуализации. Но htopпоказывает, что из 2050 МБ ОЗУ используется только 307 МБ.
Табб
Об индексах вам действительно нужно подумать о том, какие столбцы индексировать, вы не хотите просто индексировать все, индексировать столбцы с наибольшим количеством, я делаю некоторые дикие предположения по этому поводу, но я бы начал с name«firstname». Во-вторых, вы уверены, что правильно сделали индексацию? возможные_ключи: NULL, если столбец равен NULL, это означает, что не найдено соответствующих индексов.
Энтони Форнито