MySQL 5.1, Ubuntu 10.10 64bit, виртуальная машина Linode.
Все таблицы InnoDB .
Одна из наших производственных машин использует базу данных MySQL, содержащую 31 связанную таблицу. В одной таблице есть поле, содержащее отображаемые значения, которые могут изменяться несколько раз в день в зависимости от условий.
Эти изменения отображаемых значений применяются лениво в течение дня в часы использования. Сценарий периодически запускается и проверяет несколько недорогих условий, которые могут вызвать изменение, и обновляет отображаемое значение, если выполняется условие. Однако этот ленивый метод не охватывает все возможные сценарии, в которых значение дисплея должно обновляться, чтобы поддерживать минимальную нагрузку фонового процесса в рабочее время.
Один раз за ночь скрипт очищает все отображаемые значения, хранящиеся в таблице, и пересчитывает их все, тем самым фиксируя все возможные изменения. Это гораздо более дорогая операция.
Все это работает последовательно в течение примерно 6 месяцев. Внезапно, 3 дня назад, время выполнения ночного сценария изменилось в среднем с 40 секунд до 11 минут.
Общие пропорции хранимых данных существенно не изменились.
Я исследовал как мог, и часть скрипта, которая неожиданно работает медленнее, является последним оператором обновления, который записывает новые отображаемые значения. Он выполняется один раз для каждой строки с учетом (INT (11)) идентификатора строки и нового отображаемого значения (также INT).
update `table` set `display_value` = ? where `id` = ?
Самое смешное, что очистка всех предыдущих значений выполняется как:
update `table` set `display_value` = null
И это утверждение по-прежнему работает с той же скоростью, что и всегда.
Поле display_value
не проиндексировано. id
является первичным ключом. В table
есть еще 4 внешних ключа, которые не изменяются во время выполнения.
И последний изогнутый шар: если я дам эту схему в тестовую виртуальную машину и выполню тот же сценарий, он будет запущен за 40 секунд, а не за 11 минут. Я не пытался перестроить схему на производственном компьютере, поскольку это просто не долгосрочное решение, и я хочу понять, что здесь происходит.
Что-то не так с моими индексами? Они запутались в них после тысяч обновлений в тех же строках?
Обновление
Мне удалось полностью решить эту проблему, запустив оптимизацию в схеме. Поскольку InnoDB не поддерживает оптимизацию, это вызвало перестройку и решило проблему. Возможно, у меня был поврежденный индекс?
mysqlcheck -A -o -u <user> -p