Когда вы ограничиваете количество строк, возвращаемых SQL-запросом, обычно используемым в разбивке по страницам, существует два метода определения общего количества записей:
Способ 1
Включите эту SQL_CALC_FOUND_ROWS
опцию в оригинал SELECT
, а затем получите общее количество строк, выполнив SELECT FOUND_ROWS()
:
SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();
Способ 2
Запустите запрос в обычном режиме, а затем получите общее количество строк, выполнив SELECT COUNT(*)
SELECT * FROM table WHERE id > 100 LIMIT 10;
SELECT COUNT(*) FROM table WHERE id > 100;
Какой метод самый лучший / самый быстрый?
источник
SQL_CALC_FOUND_ROWS
занял более 20 секунд; использование отдельногоCOUNT(*)
запроса заняло менее 5 секунд (для обоих запросов count + result).SQL_CALC_FOUND_ROWS
будет быстрее, интересно , в каких ситуациях (если таковые имеются) , то на самом деле это быстрее!tblA
,tblB
,tblC
,tblD
,tblY
ГДЕ tblA.b = tblC.id AND tblA.c = tblB.id AND tblA.d = tblD.id AND tblA.y = tblY.idid
), потребовалось только 0,25.FOUND_ROWS()
учтите , что это устарело в MySQL 8.0.17. Смотрите также ответ @ madhur-bhaiya.При выборе «наилучшего» подхода, более важным фактором, чем скорость, может быть ремонтопригодность и правильность вашего кода. Если так, то SQL_CALC_FOUND_ROWS предпочтительнее, потому что вам нужно поддерживать только один запрос. Использование одного запроса полностью исключает тонкую разницу между запросами main и count, что может привести к неточному подсчету.
источник
MySQL начал
SQL_CALC_FOUND_ROWS
отказываться от функциональности начиная с версии 8.0.17.Таким образом, всегда предпочтительнее рассмотреть возможность выполнения вашего запроса с
LIMIT
, а затем второй запрос сCOUNT(*)
и без,LIMIT
чтобы определить, есть ли дополнительные строки.Из документов :
Кроме того,
SQL_CALC_FOUND_ROWS
было замечено, что в общем есть больше проблем, как объяснено в MySQL WL # 12615 :источник
LOCK TABLES <tablename>
иUNLOCK TABLES
. Третий вариант и (лучший ИМХО) заключается в переосмыслении нумерации страниц. Пожалуйста, прочитайте: mariadb.com/kb/en/library/pagination-optimizationСогласно следующей статье: https://www.percona.com/blog/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Если у вас есть INDEX в вашем предложении where (если id индексируется в вашем случае), то лучше не использовать SQL_CALC_FOUND_ROWS и использовать вместо него 2 запроса, но если у вас нет индекса для того, что вы поместили в ваше предложение where (id в вашем случае), тогда использование SQL_CALC_FOUND_ROWS более эффективно.
источник
ИМХО, причина, почему 2 запроса
быстрее, чем использование SQL_CALC_FOUND_ROWS
должен рассматриваться как частный случай.
Фактически это зависит от избирательности предложения WHERE по сравнению с избирательностью неявного эквивалента ORDER + LIMIT.
Как сказал Арвидс в комментарии ( http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-1174394 ) тот факт, что EXPLAIN используют, или нет, временная таблица должна быть хорошей основой для того, чтобы знать, будет ли SCFR быстрее или нет.
Но, как я добавил ( http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/#comment-8166482 ), результат действительно действительно зависит от случая. Для конкретного paginator вы можете прийти к заключению, что «для 3 первых страниц используйте 2 запроса; для следующих страниц используйте SCFR »!
источник
Удаление некоторого ненужного SQL и тогда
COUNT(*)
будет быстрее, чемSQL_CALC_FOUND_ROWS
. Пример:Тогда посчитайте без лишней части:
источник
Есть и другие варианты для сравнения:
1.) Оконная функция будет возвращать фактический размер напрямую (проверено в MariaDB):
2. Думая «из коробки», в большинстве случаев пользователям не нужно знать ТОЧНЫЙ размер таблицы, приблизительное значение часто бывает достаточно хорошим.
источник