SQL_CALC_FOUND_ROWS в MySQL

PHP & MySQLSQL_CALC_FOUND_ROWS в

Начиная от версии 4.0 в СУБД MySQL появилась достаточно удобная возможность подсчета количества всех подходящих под запрос записей, когда количество записей ограничивается LIMIT’ом. При работе с поиском в БД, а так же при выборках из таблиц с большим количеством записей такой функционал просто необходим.

Синтаксис. В запросе SELECT перед списком столбцов необходимо указать опцию SQL_CALC_FOUND_ROWS.  Вот начало описания синтаксиса конструкции SELECT.

SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr, … …

Таким образом, выполняя запрос SELECT SQL_CALC_FOUND_ROWS СУБД подсчитает полное число строк, подходящих под условие запроса, и сохранить это число в памяти. Естественно, имеет смысл запрос SELECT SQL_CALC_FOUND_ROWS только при использовании ограничения (LIMIT). Сразу после выполнения запроса на выборку для получения количества записей нужно выполнить еще один SELECT-запрос: SELECT FOUND_ROWS ();. В результате MySQL вернет одну строку с одним полем, в котором и будет храниться число строк.

Пример самих запросов:

> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE number > 100 LIMIT 10;
> SELECT FOUND_ROWS();

Первый запрос вернет (выведет) 10 строк таблицы tbl_name, для которых выполняется условие number > 100. Второй вызов команды SELECT возвратит количество строк, которые возвратила бы первая команда SELECT, если бы она была написана без выражения LIMIT. Хотя при использовании команды SELECT SQL_CALC_FOUND_ROWS, MySQL должен пересчитать все строки в наборе результатов, этот способ все равно быстрее, чем без LIMIT, так как не требуется посылать результат клиенту.

Пример запросов из PHP:

$result = mysql_query(«SELECT SQL_CALC_FOUND_ROWS * FROM table1 LIMIT 0, 10», $link);
while ($row = mysql_fetch_assoc($result))
{
var_dump($row);
}

$result = mysql_query(«SELECT FOUND_ROWS()», $link);
$num_rows = mysql_result($result, 0);
echo «$num_rows Rows\n»;

В результате выполнения кода при условии, что $link указывает на открытое соединение с СУБД, PHP выведет 10 строк из таблицы table1 , а затем целочисленное значение количества строк, соответствующих запросу (без учета LIMIT).

В запросах с UNION SQL_CALC_FOUND_ROWS может вести себя двояко из-за того, что LIMIT может появляться в нескольких местах. Счет строк может вестись для индивидуальных SELECT-запросов, или же для всего запроса после объединения.

Цель SQL_CALC_FOUND_ROWS для UNION состоит в том, что он должен вернуть количество строк, которые будут возвращены без глобального LIMIT. Условия применения SQL_CALC_FOUND_ROWS с UNION перечислены ниже:

  • Ключевое слово SQL_CALC_FOUND_ROWS должно указываться в первом операторе SELECT.
  • Значение FOUND_ROWS() будет точным только при условии применения UNION ALL. Если указано UNION без ALL, происходит исключение дубликатов, и значение FOUND_ROWS() будет лишь приблизительным.
  • Если в UNION не присутствует LIMIT, то SQL_CALC_FOUND_ROWS игнорируется и возвращается количество строк во временной таблице, которая создается для выполнения UNION.

SQL_CALC_FOUND_ROWS, SQL_COUNT_FOUND_ROWS, SQL_ FOUND_ROWS

Об авторе Валера Леонтьев

Программист PHP/MySQL.

Запись опубликована в рубрике MySQL, PHP, Web, Все рубрики с метками . Добавьте в закладки постоянную ссылку.

6 комментариев на «SQL_CALC_FOUND_ROWS в MySQL»

  1. wordpress говорит:

    А запись типа SELECT COUNT(id_item) AS count [fields…] FROM table1 LIMIT 0, 10 уже не в моде?;)

    Да и использовать перечисление полей вместо * намного экономней. Вдруг в будущем вы добавите в эту тублицу поле типа TEXT или BLOB?

    П.С.: а вообще спасибо за статью изучал исходники и нашёл страннную констану)) Бегом в яшу) По этому запросу твой сайт первый ;)

  2. Александр говорит:

    Ну и при запросе SELECT COUNT(id_item) AS count [fields…] FROM table1 LIMIT 0, 10 получим в count — 10, независимо от числа записей в таблице :)

  3. mente говорит:

    Как по мне — у вас закралась ошибка. mysql_num_rows() вернет количество строк с LIMIT, а не без него. Для возвращения количества строк без лимита, нужно использовать «SELECT FOUND_ROWS()»

  4. mente, верно. Странно, что ее не заметили до сих пор.

  5. Уведомление: Пагинация в Doctrine (Использование SQL_CALC_FOUND_ROWS) | Андрей Токарчук

  6. dterantul говорит:

    SQL_CALC_FOUND_ROWS вещь конечно хорошая, но для мелких таблиц. В моей ситуации больше 10000000 записей в таблице.висит по 2-3 минуты.

Добавить комментарий