У меня есть таблица базы данных MySQL с почти 23 миллионами записей. Эта таблица не имеет первичного ключа, потому что нет ничего уникального. Имеет 2 столбца, оба проиндексированы. Ниже его структура:
Ниже приведены некоторые из его данных:
Теперь я выполнил простой запрос:
SELECT `indexVal` FROM `key_word` WHERE `hashed_word`='001'
К сожалению, это заняло более 5 секунд, чтобы получить данные и показать их мне. В моей будущей таблице будет 150 миллиардов записей, так что на этот раз очень, очень много.
Я запустил Explain
команду, чтобы посмотреть, что происходит. Результат ниже.
Затем я запустил профиль с помощью команды ниже.
SET profiling=1;
SELECT `indexVal` FROM `key_word` WHERE `hashed_word` = '001';
SHOW profile;
Ниже приведен результат профилирования:
Ниже приведена дополнительная информация о моей таблице:
Итак, почему это занимает так много времени? Они тоже проиндексированы! В будущем мне придется запускать много LIKE
команд, так что это занимает слишком много времени. Что пошло не так?
источник
Ответы:
Вы спросили « почему это занимает слишком много времени ?». Вы также сказали: « К сожалению, это заняло более 5 секунд, чтобы получить данные и показать их мне ». Кроме того, вы сообщили о результатах профилирования вашего запроса.
Как видите, сумма времени, сообщенная профилировщиком для каждого шага, составляет 0,000154 секунды. Итак, с точки зрения профилировщика, запрос был выполнен за такое время (0,000154).
Итак, почему вы получаете результаты в « ... более 5 секунд? ».
Вы сказали, что фильтруете таблицу записей на 23 миллиона с полем из 3 символов. К сожалению, вы не сообщаете нам, сколько записей возвращает ваш запрос ... но благодаря предоставленному EXPLAIN SELECT кажется, что ваш запрос вернул 336052 записей.
Также кажется, что вся ваша деятельность проходит через некоторый графический интерфейс (PHPMyAdmin?).
Итак, после всего вышесказанного мы можем переформулировать ваш первоначальный вопрос следующим образом:
«Почему в моем графическом интерфейсе отображается 336.052 записей, отображаемых более чем за 5 секунд, если время выполнения MySQL для соответствующего запроса составляет 0,000154 секунды?»
Ответ, на мой взгляд, довольно прост: 5 секунд - это (действительно, очень мало) время, чтобы позволить 336.052 записям пройти по пути: движок MySQL => клиентские библиотеки MySQL => модуль PHP MySQL => Apache => сеть = > TCP / IP стек вашего ПК => Браузер => Парсер DOM / строитель / и т.д. => Рендеринг HTML-страницы.
Что касается моего предыдущего опыта, то время, необходимое для передачи результатов, «обычно» намного больше, чем время, необходимое для извлечения таких данных. Это особенно верно, когда задействованы такие библиотеки, как PHP-MySQL или Perl-DBD-MySQL: им действительно требуется много времени для извлечения записей после того , как MySQL правильно определил (... и извлек) все из них.
Как решить эту проблему?
Опять же, довольно легко: вы действительно уверены, что вам нужны ВСЕ записи 336.052, в одном, целом наборе данных?
Если ваш ответ действительно «ДА! Мне нужны все из них», то ваше приложение будет обрабатывать PAGINATION и / или USER-Interaction самостоятельно и ... как только оно соберет все такие данные, оно, вероятно, потратит много времени взаимодействовать с пользователем, не требуя дальнейшего взаимодействия с MySQL. В таком случае ожидание в течение 5 секунд (или даже больше) не должно быть проблемой;
Если ваш ответ «НЕТ, я хочу иметь дело с более« человеческим »размером набора данных», чем вы должны уточнить свой запрос (по крайней мере), чтобы он вернул вам более «человеческий» набор данных (десятки или, сотни, максимум, записей). В таком случае, держу пари, что вы получите свой результат в более короткие сроки.
Кстати, это точно та же проблема, с которой вы сталкивались в этом другом посте , на ServerFault: 88 секунд, чтобы позволить 132M записям путешествовать по магическому пути, не связанному с mysql :-)
источник
Проверьте mysql innodb_buffer_pool_size . Он должен быть достаточно большим - чем больше, тем лучше. Но не слишком, чтобы избежать замены ОС.
покажет размер буфера в байтах.
Проверьте запрос более одного раза. Первый запуск может быть слишком долгим, поскольку данные должны быть прочитаны с диска в память. Когда вы запускаете запрос в первый раз, данные все еще не находятся в буфере innodb и должны быть прочитаны с диска. Что намного медленнее, чем если бы данные уже были в кеше. Так что запустите запрос пару раз, чтобы убедиться, что он подается из кеша.
Отключите кэш запросов, так как каждый последующий запуск будет выполняться из него и будет смещать результаты теста. В MySQL существует механизм, называемый «кеш запросов», который предназначен для хранения запросов вместе с их результатами. Поэтому во второй раз, когда MySQL запрашивается для выполнения запроса, он может обойти выполнение и извлечь результаты из кэша запросов.
Рассмотрите возможность использования «индекса покрытия»:
Это было бы намного эффективнее, так как тогда MySQL может выполнять запрос запроса только из индекса.
источник