Мне было интересно, есть ли способ получить количество результатов из запроса MySQL и в то же время ограничить результаты.
Как работает пагинация (насколько я понимаю), сначала делаю что-то вроде
query = SELECT COUNT(*) FROM `table` WHERE `some_condition`
После того, как я получу num_rows (запрос), у меня будет количество результатов. Но затем, чтобы фактически ограничить мои результаты, я должен выполнить второй запрос, например:
query2 = SELECT COUNT(*) FROM `table` WHERE `some_condition` LIMIT 0, 10
Мой вопрос: есть ли способ получить общее количество результатов, которые будут выданы, И ограничить результаты, возвращаемые в одном запросе? Или любой более эффективный способ сделать это. Спасибо!
mysql
pagination
double
ассоциация теннисистов-профессионалов
источник
источник
Ответы:
Нет, столько приложений, которые хотят разбить на страницы, должны это делать. Он надежный и пуленепробиваемый, хотя и делает запрос дважды. Но вы можете кэшировать счетчик на несколько секунд, и это очень поможет.
Другой способ - использовать
SQL_CALC_FOUND_ROWS
предложение, а затем позвонитьSELECT FOUND_ROWS()
. Помимо того факта, что вы должны выполнитьFOUND_ROWS()
вызов после этого, существует проблема с этим: в MySQL есть ошибка , которая влияет наORDER BY
запросы, делая их намного медленнее в больших таблицах, чем наивный подход с двумя запросами.источник
Я почти никогда не делаю двух запросов.
Просто верните на одну строку больше, чем необходимо, отобразите на странице только 10, а если их больше, чем отображается, отобразите кнопку «Далее».
Ваш запрос должен возвращаться в порядке наиболее релевантного. Скорее всего, большинству людей наплевать на страницу 236 из 412.
Когда вы выполняете поиск в Google и ваши результаты не отображаются на первой странице, вы, скорее всего, перейдете на вторую, а не на девятую страницу.
источник
COUNT
- агрегатная функция. Как вернуть счет и все результаты одним запросом? Вышеупомянутый запрос вернет только 1 строку, независимо от того, какое значениеLIMIT
установлено. Если вы добавитеGROUP BY
, он вернет все результаты, ноCOUNT
будут неточнымиДругой подход к предотвращению двойных запросов состоит в том, чтобы сначала получить все строки для текущей страницы, используя предложение LIMIT, а затем выполнить второй запрос COUNT (*) только в том случае, если было получено максимальное количество строк.
Во многих приложениях наиболее вероятным результатом будет то, что все результаты умещаются на одной странице, и необходимость разбиения на страницы является скорее исключением, чем нормой. В этих случаях первый запрос не вернет максимальное количество результатов.
Например, ответы на вопрос о stackoverflow редко попадают на вторую страницу. Комментарии к ответу редко выходят за рамки 5 или около того, необходимых для того, чтобы показать их все.
Таким образом, в этих приложениях вы можете просто сначала выполнить запрос с LIMIT, а затем, пока этот предел не достигнут, вы точно знаете, сколько строк там, без необходимости выполнять второй запрос COUNT (*), который должен охватывают большинство ситуаций.
источник
В большинстве случаев гораздо быстрее и менее ресурсоемко выполнить это в двух отдельных запросах, чем в одном, хотя это кажется нелогичным.
Если вы используете SQL_CALC_FOUND_ROWS, то для больших таблиц он делает ваш запрос намного медленнее, значительно медленнее, чем выполнение двух запросов, первый с COUNT (*), а второй с LIMIT. Причина этого в том, что SQL_CALC_FOUND_ROWS приводит к применению предложения LIMIT после выборки строк, а не до, поэтому он выбирает всю строку для всех возможных результатов перед применением ограничений. Индекс не может удовлетворить это, потому что он фактически извлекает данные.
Если вы воспользуетесь подходом с двумя запросами, первый из которых извлекает только COUNT (*), а не фактически извлекает и фактические данные, это может быть выполнено гораздо быстрее, потому что он обычно может использовать индексы и не должен извлекать фактические данные строки для каждую строку, на которую он смотрит. Затем второму запросу нужно только просмотреть первые строки $ offset + $ limit, а затем вернуться.
Этот пост из блога о производительности MySQL объясняет это дополнительно:
http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Для получения дополнительной информации об оптимизации разбивки на страницы проверьте этот пост и этот пост .
источник
Мой ответ может быть запоздалым, но вы можете пропустить второй запрос (с ограничением) и просто отфильтровать информацию через свой серверный скрипт. Например, в PHP вы можете сделать что-то вроде:
Но, конечно, когда вам нужно рассмотреть тысячи записей, это очень быстро становится неэффективным. Предварительно рассчитанный подсчет, возможно, хорошая идея.
Вот хорошее прочтение по этой теме: http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf
источник
источник
where
предложение во внутренний запрос, и вы получите правильную «сумму» вместе с выгружаемыми результатами (страница выбирается с помощьюlimit
предложенияДля тех, кто ищет ответ в 2020 году. Согласно документации MySQL:
"Модификатор запроса SQL_CALC_FOUND_ROWS и соответствующая функция FOUND_ROWS () устарели в MySQL 8.0.17 и будут удалены в будущей версии MySQL. В качестве замены рассмотрим возможность выполнения вашего запроса с помощью LIMIT, а затем второго запроса с COUNT (*) и без LIMIT, чтобы определить, есть ли дополнительные строки. "
Думаю, это решает.
https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_found-rows
источник
Вы можете повторно использовать большую часть запроса в подзапросе и установить для него идентификатор. Например, запрос фильма, который находит фильмы, содержащие буквенное упорядочение по времени выполнения, на моем сайте будет выглядеть так.
Обратите внимание, что я не эксперт по базам данных и надеюсь, что кто-то сможет оптимизировать это немного лучше. Поскольку он работает прямо из интерфейса командной строки SQL, они оба занимают ~ 0,02 секунды на моем ноутбуке.
источник
источник