Очень маленький вопрос. Открываю файл логов медленных запросов, беру какой-нибудь запрос. В логах у него "Query_time: 4.812942". Запускаю этот же запрос PMA. Результат запроса действительно жду долго, но в конечном итоге PMA пишет "Запрос занял 0.1060 сек." На ум только приходит то, что время в логах - это реально затраченное время на запрос, а PMA выдает процессорное время. Это так или это какой-то баг PMA?
Я бы с этим обратился на их багтрекер, пусть разрабы репу чешут. Но похоже на баг. Попробуй тот же запрос послать из "своего PHP" и замерять время самостоятельно. Чтобы удостовериться, что это не проблема твоей версии PHP. Хотя я хз, какая может быть проблема, если надо просто из двух микротаймов получить разность...
Кеш. Повторно выполненный запрос может происходить намного быстрее. --- Добавлено --- Кроме того, PMA, неявно добавляет к селекту лимит, чтобы не получать лишнего. А в логе может быть запрос на вытягивание всего-всего. Или на получение "страницы" с большим смещением, что медленнее, чем добыча первой порции. Много нюансов.
Только это же ни на что не влияет, потому что лимит - это отсекание вывода. Уже после полного запроса.
А ты разобрался, что там по ссылке, прежде чем ее приводить? И как формируется выборка? LIMIT применяется при формировании результата. Сначала БД цепляет все строки, подходящие по условию. Выборка идет по всей таблице. Иначе бы у нас не работал корректно тот же order. Потом, когда получены указатели на все подходящие строки, идет проверка доп.условий, включая LIMIT. Если LIMIT 0,20, то, БД идет по списку, отсчитывая от нулевой строки до 20, откидывая остальное. То, что она "откусила" уходит уже как результат. Если LIMIT 480000,20, то сначала БД шаг за шагом идет до 480000 строчки. Вероятно, связано с тем, что "сырой ответ" приходит не в форме массива, а в форме связного списка, чтобы экономить память и, обеспечить максимальную гибкость. Выборки из середины у таких списков - слабое место. Как таковой структуры данных нет. Есть набор объектов, хранящих ссылку на предыдущий и на следующий элемент. За счет этого их очень легко менять местами, выбрасывать и добавлять. Почти бесплатно. Но прямого доступа к произвольному элементу нет, только через перебор ссылок. И тут именно в это место и нанесен удар. Потом отсчитывается еще 20 строк, и результат уходит в ответ. Зачем ты это линканул - я хз. Там нет ничего про снижение нагрузки от LIMIT, зато есть про ее повышение, если использовать LIMIT криво. Суть в том, что это очень частое заблуждение, что LIMIT позволяет снизить нагрузку на БД, так как если указать тот же LIMIT 0,20 то запрос, якобы, охватит лишь первые 20 строк таблицы. Но это не так. Запрос охватит всю таблицу, потом ответ будет, если надо, отсортирован, сгруппирован, и усечен до 20 записей уже в самом конце, когда все запросы были выполнены. LIMIT это всего лишь уточнение, что тебе "не надо лишнего", "хватит и N строк".
Фел, я не понял, ты вроде возражаешь, а по сути повторяешь, что лимит влияет на общую скорость выборки.
Ещё раз. Order`a может и не быть, тогда БД возьмет нужное количество строк и дальше перебирать не будет, а ещё order может быть по полю с индексом и тогда опять же запрос может быть предварительно оптимизирован перед выполнением. Оно далеко не всегда выполняется в лоб, к тому же у разных движков есть свои нюансы. Короче, не хочу я с тобой спорить, Сурикат. Я просто оставил эту ссылку здесь, что бы у людей был шанс разобраться, а не уверовать в очередные "кавычки, с которыми быстрее".
Я к тому, что неважно, что там PMA добавляет. Если запрос одинаковый и в PMA и нет, то работать будет одинаково быстро. PMA не добавляет LIMITы со смещениями безумными, а его классические 0,10/20/30 на скорость влиять не будут никак. И уж всяко не настолько, чтобы это было вообще хоть сколь-нибудь ощутимо. Если в запросе сильно сдвинутый лимит выставлен, то он выставлен явно. И будет что там, что там одинаковый эффект давать, вот я о чем. Что по-твоему произойдет при этом запросе? PHP: select * from `table` where `number`>10 limit 0,20 Ни о чем подобном вообще речь не шла. Арту сказал, что быть может дело в лимитах, выставляемых в ПМА, а я сказал, что лимиты тут не при чем. Вот и все.
Код (Text): EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 10; Seq Scan on cache (cost=0.00..290113.20 rows=238734 width=1314) (actual time=2.582..7899.051 rows=212575 loops=1) Filter: (restored_counter > 10) Rows Removed by Filter: 187445 Planning time: 0.429 ms Execution time: 7994.752 ms EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 5 LIMIT 10; Limit (cost=0.00..8.26 rows=10 width=1314) (actual time=0.024..0.076 rows=10 loops=1) -> Seq Scan on cache (cost=0.00..290113.20 rows=351384 width=1314) (actual time=0.022..0.067 rows=10 loops=1) Filter: (restored_counter > 5) Rows Removed by Filter: 14 Planning time: 0.149 ms Execution time: 0.148 ms Надо объяснять почему так? p.s. машинка загружена чуть выше максимума, индекса на поле нет. Потому такие страшные циферы )
Буду рад. Только можно сначала то же самое, но чтоб restored_counter > 10 в обоих случаях было, а не только в одном? Чтобы чище было.
Всё по 10: Код (Text): EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 10; Seq Scan on cache (cost=0.00..290113.20 rows=238734 width=1314) (actual time=0.029..7862.609 rows=212575 loops=1) Filter: (restored_counter > 10) Rows Removed by Filter: 187445 Planning time: 0.411 ms Execution time: 7959.414 ms EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 10 LIMIT 10; Limit (cost=0.00..12.15 rows=10 width=1314) (actual time=0.017..0.068 rows=10 loops=1) -> Seq Scan on cache (cost=0.00..290113.20 rows=238734 width=1314) (actual time=0.015..0.059 rows=10 loops=1) Filter: (restored_counter > 10) Rows Removed by Filter: 22 Planning time: 0.132 ms Execution time: 0.104 ms Дык вот, давай на пальцах, т.к. голова уже у самого не варит ) Представь что ты БД, тебе сказали пройтись по таблице и найти 10 записей, у которых restored_counter > 10. Зачем тебе искать все записи? Тебе не нужна вся таблица, ты находишь первые попавшиеся десять штук, отдаешь и дальше занимаешься своими делами. А вот если добавить сортировку - тогда беда, ведь тебе нужны не просто все, а самые большие по значению: Код (Text): EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 10 ORDER BY restored_counter DESC LIMIT 10; Limit (cost=295272.16..295272.18 rows=10 width=1314) (actual time=7143.120..7143.161 rows=10 loops=1) -> Sort (cost=295272.16..295868.99 rows=238734 width=1314) (actual time=7143.103..7143.127 rows=10 loops=1) Sort Key: restored_counter DESC Sort Method: top-N heapsort Memory: 45kB -> Seq Scan on cache (cost=0.00..290113.20 rows=238734 width=1314) (actual time=0.155..6888.190 rows=212575 loops=1) Filter: (restored_counter > 10) Rows Removed by Filter: 187445 Planning time: 0.721 ms Execution time: 7143.405 ms Но всё не так плохо, если глупый программист не забыл добавить индекс. По нему ты находить сразу то что нужно: Код (Text): EXPLAIN ANALYSE SELECT * FROM cache WHERE restored_counter > 10 ORDER BY restored_counter DESC LIMIT 10; Limit (cost=0.42..26.89 rows=10 width=1314) (actual time=0.036..0.072 rows=10 loops=1) -> Index Scan Backward using cache_restored_counter_index on cache (cost=0.42..551942.59 rows=208538 width=1314) (actual time=0.034..0.065 rows=10 loops=1) Index Cond: (restored_counter > 10) Planning time: 0.343 ms Execution time: 0.115 ms Я к тому, что все не так однозначно, большие запросы с джоинами и прочими вложенными выборками нужно рассматривать отдельно, что бы понять в каком цикле начинает тормозить, какие индексы при этом применяются, какие нет, а какие следует добавить. И не по принципу "какие поля ищу, те и воткну", а лишь то что реально ищется на данном этапе, т.к. неправильно составленные или лишние индексы будут скорее тормозить, чем ускорять. Вот такое шаманство )
Пока ходил в магазин, кажется понял почему мы друг друга не понимаем. Есть два предельных случая: 1. Нам надо выбрать первые 10 записей 2. Нам нужно выбрать последние 10 записей. Во втором случае нас ждет перебор всех позиций, т.к. сначала придется отсеять все что было до. И вот тогда LIMIT ни чем не поможет в плане ускорения выборки.
Окей, я понял о чем ты, да, ты прав, это логично, и оптимизация тут к месту. При ордере или групбае, соответственно, ее бы уже не было. Итог: @Deonis, покажи запрос чтоль.
Увы, но я логи уже очистил. Если примерно, то там был с десяток "OR FIND_IN_SET()" + ко всему "AND product_id IN( около 200 id-шников )".
@Fell-x27не разливаясь мыслью по древу, скажу: да, дофига случаев, когда движок вынужден сделать выборку во временную таблицу, а затем что-то там фильтровать и сортировать. но 1. глупо утверждать, что лимит никак не влияет на скорость выполнения запроса. 2. очевидно, что PMA неявно может подставить что-то типа LIMIT 20, а никак не LIMIT 1000000, 20 о чем мы толкуем, не потерял ли ты нить, родной? --- Добавлено --- И ещё, не забывайте про принцип неопределённости Гайзенберга. наблюдатель влияет на характеристики наблюдаемого процесса. Пытаясь посмотреть почему у нас запрос медленный, мы загоняем его в кеш, набираем движку статистику, тем самым ускоряя отдачу. А в слоу лог у нас лег отчет о запросе, выполненном когда-то в неблагоприятных условиях. "Удачные" разы туда не попадают по определению. Поэтому картинка расходится. --- Добавлено --- Хочешь посмотреть как работает запрос без кеша — делай SELECT SQL_NO_CACHE --- Добавлено --- И даже при этом картина не повторится на 100%. Потому что сервер откажется от кеширования результатов, но исходные данные могут быть "разогреты". http://stackoverflow.com/questions/6666631/sql-no-cache-does-not-work