Перейти к публикации

Рекомендованные сообщения

Уважаемые разработчики.

Убедительно прошу вас отказаться от использования SQL_CALC_FOUND_ROWS в запросах, заменив такие запросы на два последовательных:

1) получение числа записей, воспользовавшись COUNT(*);

2) получение непосредственно данных.

Если на маленьких сайтах проблем можно и не заметить, то на больших тормоза будут невероятными. После замены скорость выполнения возрастает на порядки.

Объясню почему.

Если мы пытаемся получить из некой таблицы, скажем, 10 записей, воспользовавшись при этом SQL_CALC_FOUND_ROWS для подсчета общего числа строк, то MySQL после 10-ой записи просто перестает выдавать нам строки, но продолжая выбирать оставшиеся... При 100 записях разница может быть незаметна, но на 100 000... весьма и весьма.

Для примера, имеем таблицу dle_comments с примерно 120 тысячами записей. Запрос с SQL_CALC_FOUND_ROWS выполняется от 5 секунд, а два отдельных запроса требуют менее сотой доли секунды.

Ссылка на сообщение
Поделиться на других сайтах

Я бы порекомендовал вам обратится к документации MySQL, а именно в раздел оптимизации MySQL запросов. Т.к. у вас неверное понимание принципов работы MySQL. Цитата из официальной документации:

SQL_CALC_FOUND_ROWS, MySQL must calculate how many rows are in the full result set. However, this is faster than running the query again without LIMIT, because the result set need not be sent to the client.

Я выделил информацию о том что быстрее. SQL_CALC_FOUND_ROWS не продолжает выборки, он делает выборку нужного количества, потом просто продолжает подсчет в этом же запросе.

А вот цитата из того для чего разработчики добавили эту функцию:

SQL_CALC_FOUND_ROWS and FOUND_ROWS() can be useful in situations when you want to restrict the number of rows that a query returns, but also determine the number of rows in the full result set without running the query again. An example is a Web script that presents a paged display containing links to the pages that show other sections of a search result. Using FOUND_ROWS() allows you to determine how many other pages are needed for the rest of the result.

Поэтому все тормоза на больших данных, это результат неверно настроенного MySQL, я могу привести реальные сайты имеющие более полумиллиона записей и с очень большой посещаемостью, не имеющих проблем с тормозами. Да и оснований недоверять разработчикам MySQL, которые утвержают, что это работает быстрее у меня нет.

Для примера, имеем таблицу dle_comments с примерно 120 тысячами записей. Запрос с SQL_CALC_FOUND_ROWS

для dle_comments кстати не применяется выборка SQL_CALC_FOUND_ROWS, она применяется для таблицы _post

Ссылка на сообщение
Поделиться на других сайтах

Я бы порекомендовал вам обратится к документации MySQL, а именно в раздел оптимизации MySQL запросов. Т.к. у вас неверное понимание принципов работы MySQL. Цитата из официальной документации:

SQL_CALC_FOUND_ROWS, MySQL must calculate how many rows are in the full result set. However, this is faster than running the query again without LIMIT, because the result set need not be sent to the client.

Я выделил информацию о том что быстрее. SQL_CALC_FOUND_ROWS не продолжает выборки, он делает выборку нужного количества, потом просто продолжает подсчет в этом же запросе.

Обратите внимание на основную часть в выделенном фрагменте - this is faster than running the query again without LIMIT, то есть он будет работать быстрее, но только если запрашиваются все данные из таблицы.

Поэтому все тормоза на больших данных, это результат неверно настроенного MySQL, я могу привести реальные сайты имеющие более полумиллиона записей и с очень большой посещаемостью, не имеющих проблем с тормозами. Да и оснований недоверять разработчикам MySQL, которые утвержают, что это работает быстрее у меня нет.

К сожалению, практика подтверждает тормоза подобных запросов. На своем проекте (около миллиона просмотров страниц в день, собственный двиг, обслуживает один сервер) я отказался от SQL_CALC_FOUND_ROWS еще 4 года назад. У знакомого ваш двиг, сервер мощнее, но тормозит уже на 150 тысячах просмотров в день (не уникальных посещений, а именно просмотров страниц).

для dle_comments кстати не применяется выборка SQL_CALC_FOUND_ROWS, она применяется для таблицы _post

Я этого не придумал, а увидел в slow-логе mysql-сервера:

SELECT SQL_CALC_FOUND_ROWS dle_comments.id, post_id, dle_comments.user_id, dle_comments.date, dle_comments.autor as gast_name, dle_comments.email as gast_email, text, ip, is_register, name, dle_users.email, news_num, dle_users.comm_num, user_group, reg_date, signature, foto, fullname, land, dle_users.thanks_num, dle_users.thanks_sayed, icq, dle_users.xfields as xprofile, dle_post.title, dle_post.date as newsdate, dle_post.alt_name, dle_post.category, dle_post.flag FROM dle_comments LEFT JOIN dle_post ON dle_comments.post_id=dle_post.id LEFT JOIN dle_users ON dle_comments.user_id=dle_users.user_id ORDER BY date desc LIMIT 0,10;

я могу привести реальные сайты имеющие более полумиллиона записей и с очень большой посещаемостью, не имеющих проблем с тормозами.

Покажите пожалуйста примеры. И, если возможно, конфигурацию сервера, в том числе настройки MySQL-сервера.

Изменено пользователем Wildev
Ссылка на сообщение
Поделиться на других сайтах

Я этого не придумал, а увидел в slow-логе mysql-сервера:

У вас устаревшая версия скрипта, в более старых версиях не не предусмотрел что подчет будет в трех таблицах, а нужно в одной, но тем не менее именно подчет, а не выборка информации из бд. И указанный вами запрос медленный не потому что SQL_CALC_FOUND_ROWS это плохо, а потому что я не предусмотрел что считаются и объединяются три полные таблицы, и то это уже исправлено в актуальной версии скрипта, поэтому собственно бессмысленно просить сделать то что уже сделано.

Покажите пожалуйста примеры. И, если возможно, конфигурацию сервера, в том числе настройки MySQL-сервера.

http://www.rusfootball.info/?do=stats

http://epidem.ru/?do=stats

Обратите внимание на основную часть в выделенном фрагменте - this is faster than running the query again without LIMIT, то есть он будет работать быстрее, но только если запрашиваются все данные из таблицы.

у вас плохо с английским, я конечно не эксперт в переводах, но где вы увидели в этом тексте: но только если запрашиваются все данные из таблицы. Или то что незнаю сам додумаю. Помойму четко написано this is faster than running the query again without LIMIT, because the result set need not be sent to the client. слово because переводится как "потому что" а не как "но только". т.е. не идет выборка данных и выдача клиенту, просто считается количество, что собственно и делает count() Только делает это вторым запросом а не одним.

Ссылка на сообщение
Поделиться на других сайтах

Я не занимался переводом приведенной Вами фразы, а лишь пытался объяснить особенности работы с SQL_CALC_FOUND_ROWS.

Вот еще некоторая информация к размышлению...

http://dev.mysql.com/doc/refman/5.0/en/lim...timization.html

As soon as MySQL has sent the required number of rows to the client, it aborts the query unless you are using SQL_CALC_FOUND_ROWS.

http://forum.mysqlperformanceblog.com/s/m/37/

If SQL_CALC_FOUND_ROWS is used what happens is - MySQL Simply stops sending rows back to the client after LIMIT clause is satisfied - they still however need to be internally retrieved to be counted.

http://stackoverflow.com/questions/186588/...or-select-count

http://www.mysqlperformanceblog.com/2007/0...alc_found_rows/

P.S. http://epidem.ru/?do=lastcomments - ждал ответа от сервера 8 секунд, со связью у меня все в порядке.

Изменено пользователем Wildev
Ссылка на сообщение
Поделиться на других сайтах

Вообщем оставайтесь при своем мнении, переубеждать я вас не буду. Вы ничего не поняли, по одной простой причине. Это называется слышу звон не знаю о чем он.

Запрос:

SELECT * FROM WHERE x=y LIMIT 0,10

выстроил ряды и вывел первые десять тут же идет запрос

SELECT count(*) FROM WHERE x=y

Опять выстроил ряды по критерию и посчитал количество строк, лимита во втором запросе нет, и он выстроит все ряды

А теперь запрос

SELECT SQL_CALC_FOUND_ROWS * FROM WHERE x=y LIMIT 0,10

выстроил все ряды согласно WHERE вывел первые десять остальные посчитал. В отличие от первого варианта он сделал это за один раз.

Фраза

As soon as MySQL has sent the required number of rows to the client, it aborts the query unless you are using SQL_CALC_FOUND_ROWS.

Означаете то что при использовании LIMIT запрос будет остановлен по достижении нужного ряда, при SQL_CALC_FOUND_ROWS он его не остановит. Читайте название раздела: LIMIT Optimization Но по видимому забыли что для подсчета количества строк вы вторым запрос выполняете SELECT count(*) FROM WHERE x=y в котором НЕТ!!!!!!!!! лимита. Т.е. в первом варианте вы выполнили запрос и прервали его на 10 строке, вторым запросом опять сделали выстроение рядов но не прерываете его потому что нужно посчитать ряды.

Запустите в цикле 1000 запросов по первому варианту и по второму и засеките время, вы это делали? Я делал.

Единственно что нельзя делать, так это применять SQL_CALC_FOUND_ROWS когда идет объединение таблиц, тогда подсчет будет медленнее, что собственно и сказано в ваших ссылках. такую ошибку в одном запросе я сделал, но уже исправил.

Ссылка на сообщение
Поделиться на других сайтах

Запустите в цикле 1000 запросов по первому варианту и по второму и засеките время, вы это делали? Я делал.

Как-то хотели сделать, не добрались)))

Ссылка на сообщение
Поделиться на других сайтах

Всё зависит от коннкретного запроса, в одном выйгрыш даёт использование 2 запросов в другом включение в запрос подсчёт строк.

Вот небольшая статейка сравнение этих методов использования.

Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете опубликовать сообщение сейчас, а зарегистрироваться позже. Если у вас есть аккаунт, войдите в него для написания от своего имени.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

×
×
  • Создать...