MySQL-запрос к таблице среднего размера быстро в одной системе, медленнее в другой

У меня есть следующая таблица с примерно 40 тысячами строк:

CREATE TABLE IF NOT EXISTS `log_ui_activity` (
    `uiActivityLogEntryId` INTEGER UNSIGNED auto_increment ,
    `uid` INTEGER UNSIGNED,
    `from` DATETIME,
    `duration` INTEGER UNSIGNED,
    `nCharactersTyped` INTEGER UNSIGNED,
    `nClicks` INTEGER UNSIGNED,
    `hadOtherInteractions` INTEGER UNSIGNED,
    `currentPage` TEXT,
    `currentPageArgs` TEXT,
    `currentPageStateInfo` TEXT,
    `createdAt` DATETIME NOT NULL,
    `updatedAt` DATETIME NOT NULL,
    PRIMARY KEY (`uiActivityLogEntryId`)
) ENGINE=InnoDB;

с двумя дополнительными индексами, каждый на createdAt и uid.

Когда я запускаю следующий запрос:

SELECT *
    FROM log_ui_activity
    WHERE `createdAt` IN (
        SELECT MAX(`createdAt`) FROM log_ui_activity
                  GROUP BY uid);

Он завершается в течение 0,2 с в Windows 7 и запускает XAMPP с:

MySql Ver 14.14 Distrib 5.6.20 для Win32 (x86)

Однако выполнение одного и того же запроса к точной копии данных на Mac Pro занимает несколько минут (проверено: структура, индексы и движок одинаковы) с MAMP с:

MySql Ver 14.14 Distrib 5.5.38 для osx10.6 (i386) с использованием оболочки EditLine

Я даже пробовал разных клиентов ...

Есть идеи, как запрос может быть намного медленнее, даже если все / кажется идентичным?

ОБНОВЛЕНИЕ

Как предлагается в ответе, использование JOIN вместо IS IN исправляет ситуацию. Для справки это выражение JOIN:

SELECT *
    FROM log_ui_activity a
    INNER JOIN (
    (SELECT MAX(`createdAt`) createdAt FROM log_ui_activity GROUP BY uid) tmp
    )
    ON (a.createdAt = tmp.createdAt);

person Domi    schedule 31.03.2015    source источник
comment
Если вы сделаете EXPLAIN в каждой системе, будут ли результаты одинаковы? Вы недавно перестраивали индексы в обеих системах?   -  person Kickstart    schedule 31.03.2015
comment
@Kickstart Спасибо за информацию! EXPLAIN показывает то же самое. Однако я думал, что создание индекса для существующей таблицы (с использованием CREATE INDEX) фактически построит индекс. Я также обнаружил, что InnoDB не поддерживает REPAIR, так что теперь я пытаюсь использовать метод mysqldump.   -  person Domi    schedule 31.03.2015
comment
Проблема, похоже, не в самих индексах, а в статистике, которую MySQL использует, чтобы решить, какие индексы использовать. Этот другой ответ может помочь - stackoverflow.com/ questions / 321461 /   -  person Kickstart    schedule 31.03.2015


Ответы (1)


IN ( SELECT ... ) имел ужасную производительность. Обычно вы могли "исправить" это, превратив его в JOIN. Проблема заключалась в том, что SELECT выполнялся повторно каждый раз, когда требовалось IN.

В версии 5.6.5 оптимизатор делает что-то более интересное. Вы можете увидеть "изменение", выполнив EXPLAIN EXTENDED SELECT ..., затем SHOW WARNINGS.

person Rick James    schedule 31.03.2015
comment
Просто протестировал. Использование INNER JOIN вместо IS IN обеспечивает выполнение запроса за 93 мс. Заметив такую ​​тонкую разницу между версиями; это неплохое понимание, спасибо! - Да еще, я случайно отменил и переделал ваши правки по моему вопросу, но ТАК, похоже, есть ошибка, из-за которой в этом случае вас больше не аккредитуют. - Прости! Не стесняйтесь, сделайте еще одну правку :) - person Domi; 02.04.2015
comment
Рад слышать, что он быстро работает. 93 мс против 0,2 с означает, что JOIN удвоил скорость; это интересно знать. Спасибо за ответ. Нет проблем (по поводу редактирования); так или иначе, история изменений показывает подробности. - person Rick James; 03.04.2015
comment
Прости! 93 мс от Mac Pro, что быстрее, чем на ПК с Windows, где потребовалось 200 мс. Я просто перепроверил и выяснил, что да: JOIN еще быстрее. На ПК с Windows (более новая версия MySQL) IS IN занимает от 150 до 220 мс, а версия JOIN - от 90 до 150 мс. ПРИМЕЧАНИЕ. Я повторил запрос только несколько раз и записал время запроса; не очень надежная установка для тестирования производительности. - person Domi; 03.04.2015