Какой самый быстрый? SELECT SQL_CALC_FOUND_ROWS FROM `table` или SELECT COUNT (*) - PullRequest
161 голосов
/ 09 октября 2008

Когда вы ограничиваете количество строк, возвращаемых 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;  

Какой метод самый лучший / быстрый?

Ответы [ 7 ]

111 голосов
/ 09 октября 2008

Это зависит. См. Блог MySQL Performance Blog на эту тему: http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/

Просто краткое резюме: Питер говорит, что это зависит от ваших показателей и других факторов. Многие комментарии к посту, кажется, говорят, что SQL_CALC_FOUND_ROWS почти всегда медленнее - иногда до 10 раз медленнее - чем выполнение двух запросов.

18 голосов
/ 19 декабря 2013

При выборе «наилучшего» подхода более важным фактором, нежели скорость, может быть ремонтопригодность и правильность вашего кода. Если это так, SQL_CALC_FOUND_ROWS предпочтительнее, потому что вам нужно только поддерживать один запрос. Использование одного запроса полностью исключает тонкую разницу между запросами main и count, что может привести к неточному подсчету.

13 голосов
/ 22 июня 2015

Согласно следующей статье: 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 более эффективно.

8 голосов
/ 04 августа 2014

ИМХО, причина, по которой 2 запроса

SELECT * FROM count_test WHERE b = 666 ORDER BY c LIMIT 5;
SELECT count(*) FROM count_test WHERE b = 666;

быстрее, чем использование SQL_CALC_FOUND_ROWS

SELECT SQL_CALC_FOUND_ROWS * FROM count_test WHERE b = 555 ORDER BY c LIMIT 5;

следует рассматривать как частный случай.

Фактически это зависит от селективности предложения 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),, результат действительно, действительно зависит от случая. Для конкретного пагинатора можно прийти к выводу, что «для 3 первых страниц используйте 2 запроса; для на следующих страницах используйте SCFR ”!

6 голосов
/ 07 апреля 2016

Удаление ненужного SQL, а затем COUNT(*) будет быстрее, чем SQL_CALC_FOUND_ROWS. Пример:

SELECT Person.Id, Person.Name, Job.Description, Card.Number
FROM Person
JOIN Job ON Job.Id = Person.Job_Id
LEFT JOIN Card ON Card.Person_Id = Person.Id
WHERE Job.Name = 'WEB Developer'
ORDER BY Person.Name

Тогда считайте без лишних частей:

SELECT COUNT(*)
FROM Person
JOIN Job ON Job.Id = Person.Job_Id
WHERE Job.Name = 'WEB Developer'
2 голосов
/ 16 апреля 2019

MySQL начал устаревать функциональность SQL_CALC_FOUND_ROWS, начиная с версии 8.0.17.

Итак, всегда предпочтительнее рассмотреть возможность выполнения вашего запроса с LIMIT, а затем второй запрос с COUNT(*) и без LIMIT, чтобы определить, есть ли дополнительные строки.

Из документов :

Модификатор запроса SQL_CALC_FOUND_ROWS и сопровождающий FOUND_ROWS () функция устарела с MySQL 8.0.17 и будет удалена в будущая версия MySQL.

COUNT (*) подлежит определенной оптимизации. SQL_CALC_FOUND_ROWS приводит к отключению некоторых оптимизаций.

Вместо этого используйте эти запросы:

SELECT * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT COUNT(*) WHERE id > 100;
1 голос
/ 29 апреля 2019

Есть и другие варианты для сравнения:

1.) Оконная функция будет возвращать фактический размер напрямую (протестировано в MariaDB):

SELECT 
  `mytable`.*,
  COUNT(*) OVER() AS `total_count`
FROM `mytable`
ORDER BY `mycol`
LIMIT 10, 20

2.) Думая «из коробки», большую часть времени пользователям не нужно знать размер таблицы EXACT , приблизительный пример часто достаточно хорош. 1012 *

SELECT `TABLE_ROWS` AS `rows_approx`
FROM `INFORMATION_SCHEMA`.`TABLES`
WHERE `TABLE_SCHEMA` = DATABASE()
  AND `TABLE_TYPE` = "BASE TABLE"
  AND `TABLE_NAME` = ?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...