2017-01-27 9 views
0

Я планирую перейти с общего размещенного сервера на установку AWS (EC2 для apache/php, RDS для MySQL).mysql query slow после MyISAM -> InnoDB и переход на AWS

У меня была бета-версия моего сайта php/mysql, работающего на общем сервере более года. Одна страница, в частности, всегда работала быстро (возможно, < 3 секунды для полной загрузки) в браузере.

При подготовке к перемещению я изменил базу данных и все таблицы от MyISAM до InnoDB. Я также переключил набор символов по умолчанию на utf8mb4 (был латинский-1 или что-то еще) и сопоставление с utf8mb4_unicode_ci. Были несколько столбцов, которые были чем-то вроде varchar2 (400), которые были проиндексированы, которые получили ошибку символа> 191 (из-за перехода от 3 байт-> 4 байта с utf8mb4). Я вошел и вручную включил только эти столбцы в UTF-8/utf_unicode_ci. Кажется, что все выглядит нормально (нет явных ошибок)

Теперь я переместил копию сайта/DB в AWS. Большинство страниц загружаются штрафом. Это, в частности, требуется навсегда для загрузки (> 5 минут). У меня есть довольно маленькие экземпляры EC2 и экземпляры RDS, поэтому я понимаю, что это может быть проблемой, но я единственный, кто использует сайт (для одного запроса), а вся база данных - < 70MB.

Запуск плана объяснения показывает, что в большинстве случаев используются ключи (индексы?) И одна «производная» таблица с 74 тыс. Строк. 74k - очень маленький набор данных. Я гораздо больше знаком с Oracle, объясняющим планы, поэтому мне сложно понять, что происходит.

Я попытался запустить исходную страницу на общем сервере хостинга, и он стал намного медленнее! Поэтому у меня нет оснований полагать, что это проблема AWS.

Я знаю, что MyISAM немного быстрее в простых сценариях, но не может быть 10000000000000x быстрее, чем мое новое использование InnoDB?

Что-то не так с преобразованием, где он пытался индексировать varchars с> 191 символом? возможно ли это как-то сломать систему/таблицы? Запросы будут завершены, если вы дадите им массу времени, но они не должны быть такими медленными. Я бы подумал, что даже если индексы были обжарены, и он выполнял полные сканирующие таблицы на 74 тыс. Строк, он не должен даже ломать пот.

Мысли?

Edit: Найдена эта тема: https://dba.stackexchange.com/questions/75091/why-are-simple-selects-on-innodb-100x-slower-than-on-myisam Плакат, кажется, есть подобный опыт замедления. Я не могу использовать то же самое решение, что и он. Это безумие думать, что мне придется поместить все столбцы, которые я хочу вернуть в индекс. Не так ли, что все просто принимают?

+0

[_More conversion tips_] (https://mariadb.com/kb/ru/mariadb/converting-tables-from-myisam-to-innodb/). –

ответ

0

Хорошо, я понял. Была моя ошибка (неудивительно). Я написал запрос давным-давно, прежде чем я действительно знал, что делаю. Было определенно место для улучшения ...

Запрос смотрел что-то вроде:

TableA (main table of focus) 
    aID (pk) 
    bID (fk) 
    locationID (fk) 
    rowTitle 

TableB 
    bID (pk) 
    locationID (fk) 

TableLocations 
    locationID (pk) 
    locationName 

Я хотел в основном использовать местоположение А, если он существовал, но падать обратно на место Б, если А не один. (A всегда будет связано с B).

я делал некоторые, как

SELECT 
    rowTitle, 
    locationName 
FROM 
    TableA a, TableB b, TableLocations loc 
WHERE 
    a.bID = b.bID 
    AND 
    (a.locationID = loc.locationID 
    OR 
    (a.locationID IS NULL AND b.locationID = loc.locationID) 
) 

Он работал хорошо, и всегда возвращается то, что я хотел при использовании MyISAM. И это было очень быстро.Тем не менее, sh $ & ударил по стене, когда я переехал к InnoDB по какой-то причине. Не знаю, как отличаются двигатели, когда дело доходит до выполнения планов этого запроса. Я предполагаю, что в какой-то момент MyISAM задохнется, когда набор данных станет достаточно большим, но поскольку я все еще в dev/uat, данные малы.

Я с тех пор переехал к чему-то структурно лучше, как:

SELECT 
    rowTitle 
    CASE WHEN loc1.locationID IS NOT NULL THEN loc1.locationName 
     WHEN loc2.locationID IS NOT NULL THEN loc2.locationName 
    END as locationName 
FROM 
    TableA a 
JOIN TableB b ON a.bID = b.bID 
LEFT OUTER JOIN TableLocations loc1 ON a.locationID = loc1.locationID 
LEFT OUTER JOIN TableLocations loc2 ON b.locationID = loc2.locationID 

И все прекрасно работает! Я вырезал много запросов и других таблиц, чтобы сосредоточиться на моей основной логической/физической проблеме.

Запросы до 10MS, что я ожидаю.

Это единственное, что я люблю и ненавижу в отношении MySQL. Иногда «это просто работает», и давайте посмотрим на ваши собственные недостатки. Определенно, моя вина здесь не для того, чтобы не делать это правильно в первый раз ...

Дополнительный вопрос: Если кто-то знает разницу между тем, как MyISAM vs InnoDB оценил первый (плохой) запрос и почему производительность была настолько различной, я бы очень хотел это услышать!

Спасибо!

+0

Итак ... Какова ценность вашего 'innodb_buffer_pool_size'? Позвольте мне угадать - 128 МБ? :) Как проверить: 'SHOW VARIABLES LIKE '% innodb_buffer_pool%';' – Mjh

+0

Измените buffer_pool на 70% доступной ОЗУ, ниже 'key_buffer_size' до 30M. –

+0

innodb_buffer_pool_size = 625999872 (по умолчанию это означает, что AWS/RDS устанавливает его как). – user3249281