07:07
-2
Q: Долгий SELECT запрос через PDO

Дима ЙЕсть mysql запрос через PDO $statement = $this->database->getConnection()->prepare( 'SELECT a, b, c, d, e, f, g, h, timeReceipt FROM data WHERE idModem = :idModem AND timeReceipt BETWEEN :startTime AND :endTime order by timeReceipt ASC' ); $statement-

phpmyadmin выполняет запрос с лимитом (он не явный, но выводит только 25 результатов по умолчанию). Такой запрос всегда проще обработать! Особенно если много текстовых данных нужно получить.
user620291
А разве LIMIT отрабатывает не после того как будут найдены все записи удовлетворяющие критерию поиска?
@ПиуПиу причем тут когда обрабатывается лимит? В вопросе сначала делается запрос, И! обрабатываются все его записи! (привет fetchAll ). Положить все 720 строк в массив не такая быстрая работа как кажется!
user620291
@AndreyMihalev Ваше верхнее утверждение противоречит нижнему :) Логика работы СУБД такова, что вначале она все равно получит ВСЕ записи удовлетворяющие критерию отбора и только потом из них выведет кол-во указанное в LIMIT - таким образом утверждение, что запрос с лимитов проще обработать и он выполнится быстрее неверно.
Используются 2 индекса - и оба индекса для данного запроса ни о чём.. удалите оба (или по крайней мере первый) и создайте композитный индекс. через microtime на этот фрагмент уходит около 5 секунд. Профилируйте запрос и накладные расходы на него. Полагаю. основное время уходит не на выполнение запроса, а на передачу данных.
07:07
@AndreyMihalev у вас правильная идея про лимит, но совершенно дикая фантазия про 720 записей. Положить все 720 строк в массив - это настолько же ни о чём, насколько и положить 25. Если бы речь шла о всех 7 миллионах - тогда бы ваша догадка про лимит была верной.
Чисто пальцем в небо, я бы предположил дебильную реализациию getConnection() и стандартный таймаут при коннекте. И стандартно же предложил поменять localhost на 127.0.0.1 в параметрах соединения. Ну и в целом измерять только запрос, без соединения.
@ПиуПиу во-первых, зависит от запроса. в данном случае надо найти все записи, чтобы отсортировать их. Но при нормальном запросе, если брать из уже отсортированного индекса, то не обязательно ждать все. Во-вторых, данные надо не только отобрать, но и передать клиенту. И здесь разница во времени у запросов с лимитом и без лимита может быть значительной. Это как раз классический ответ на вопрос "в пма быстро, а в пхп медленно"
Как вариант, Akina прав и проблема таки в индексе, а в пма запрос тупо закэшировался. Но тут зависит от того, сколько всего записей с данным idModem. Если тысячи, то прфиг. Если миллионы - то, как и говорит Akina, надо удалить индекс timeReceipt и создать по (timeReceipt,idModem). А если бд не захочет его использовать, то заставить силой
@ПиуПиу, научитесь читать! У меня не было слов про ускорение запроса в СУБД, писал только про ОБРАБОТКУ запроса! (в данном случае обработка результата запроса в php через метод fetchAll).
@AndreyMihalev не нужно так нервничать. Особенно делая такие заявления, как "Положить в массив 720 строк требует огромной вычислительной мощности".
@Ипатьев первое: 720 строк это не такая быстрая работа как кажется - это скорее про свободные ресурсы а не вычислительные мощности, плюс не понятно какие там реальные данные, может там половина данных в swap улетает. второе: я абсолютно спокоен, пока не начинают доказывать обратное. бревна в глазах уберите потом поговорим.
композитный индекс нужен очевидно. Два индекса, как вы тут пишите (вероятно для фильтрации один, для сортировки другой) использовать не могут, такого не бывает. Две индекса только в случае index merge при фильтрации могут быть применены, когда у вас через OR объединяются условия подходящие под разные индексы.
судя по тому, что в плане там 5% строк таблицы, то этих idmodem не так уж много. Но и интервал времени судя по всему вы выбираете довольно большой в параметрах, раз СУБД решает выбрать менее селективный индекс. Так что посмотрите, какой вариант будет удобнее (id, time) или (time,id) относительно остальных запросов.
Если убрать сортировку, то насколько сократится время?
07:07
Обидно, что автор забил на свой вопрос. С другой стороны, он нам ничего не должен
@Ипатьев Спасибо за варианты. Я не забил. Все прочитал. Еще задачи сейчас навалились(+ сложности работы с бд на хостинге где лимит на время запроса). На данный момент добавил составной индекс(timeReceipt,idModem)-немного помог когда выдача ~250000 строк. Время сократилось с 16с до 7с, но на малых результатах до 1000 строк скачет от 0.2 до 3 секунд (замеры microtime). Но если запускать запрос (где результат 250к) напрямую В phpmyadmin с SQL_NO_CACHE то все равно результат 0.007. Профилирование еще в плане освоить как тут писал Akina. в течение 7 дней вернусь с результатами
Ну вам же уже объяснили про "где результат 250к"! Которые вдруг появились из ниоткуда вместо 720 строк. Сделайте в phpmyadmin лимит 250000 вместо 50 и ответа вообще не дождётесь. Вот вам и разгадка этой тайны
@AndreyMihalev напишете ответ? Вопрос не частый, но периодически находятся гении, которых он ставит в тупик. А готового я на русском не нашёл, так что по сути ответ нужен, а вы первый, кто правильно определил причину