всем салют. озадачился вот какой проблемой, как бы пооптимальнее сделать пагинацию? проблема в чем? для пагинации нужно знать количество выводимых на странице айтемов (это не проблема есессно) и количество записей в таблице (это проблема). мне видится два способа: 1. за один селект получаем все записи, тем самым узнаем количество записей - это плюс, но минус очевиден - объем возвращаемых данных и лишнее время на фетч (хотя, подозреваю, можно сделать какой-то seek). 2. два запроса к базе. первый - select count(*)... получаем количество записей, второй select ... limit page_num * page_size, page_size. собственно, все, что являлось в предыдущем подходе плюсом становиться минусом и наоборот. вопрос: есть ли какой-нибудь третий способ?
Первый способ допустим только если база маленькая, и по каким либо причинам неразумно/трудно/лень/итд использовать второй способ. (я использую на своей гостевухе, БД у меня в файле, по этому в 10000 раз проще реализовать чем второй способ) Второй способ идеален для работы с СУБД.
если таблица к которой идет обращение не слишком большая, запрос хорошо оптимизирован и нет существенной разницы во времени исполнения между запросом затрагивающий все строки и лимитированным то имеет смысл одним запросом вытягивать все значения. mysql_num_rows() этой функцией получить общее количество записей, ограничить вывод строк в рнр цикле. если же количество возвращаемых строк достаточно велико, или запрос сложен и есть существенная разница, вытянуть 10 строк или же 10000, то в этом случае конечно двумя запросами будет рациональней. Третьего способа не встречал, но вполне возможно он есть.
ну вот для мускуля, к примеру, можно такой сделать трик: [sql]select mysc.*, isch.table_rows from my_schema.my_table mysc join information_schema.tables isch on isch.table_schema='my_schema' and isch.table_name='my_table' limit 20, 10; [/sql] здесь мы приджоинили столбец с количеством строк таблицы. способ может и не самый красивый, но оптимальнее первых двух. в других субд также существует подобие information_schema, хотя меня конкретно интересует мускуль. что скажете?
с тем же успехом можно создать вьюху с подсчетом кол-ва строк внутри рабочей БД и использовать ее, мне кажется так будет быстрей работать, хотя могу заблуждаться - эксперимент не ставил
Тема уже поднималась. Если вкратце, то есть два варианта вариант 1- если не используется group by и distinct, то лучше использовать два запроса первый запрос на выборку записей с использованием limit, а второй тот же запрос только вместо полей вывода подсчет числа записей запрос на выборку $query="select name, code from users where code>100 limit 0,10"; запрос на получение числа записей $query="select count(*) from users where code>100"; вариант 2- если используется group by или distinct, то использовать запрос со словом SQL_CALC_FOUND_ROWS для выборки самих записей с использованием limit, а число записей получать используя функцию FOUND_ROWS() на выборку $query="select name, code from users where code>100 group by user_group limit 0,10"; на получение числа записей $query="select FOUND_ROWS()";
runner 1. искал, не нашел похожих тем. 2. SQL_CALC_FOUND_ROWS - я так понимаю, вернет количество строк датасета, а он ведь лимитрован выражением limit - отсюда мы не узнаем количество строк всей таблицы. [vs] число строк и так хранится в другой таблице (information_schema.tables). другое дело, что count не просто всех записей таблицы нужно знать, а кол-во отфильтрованных записей (напр. результаты поиска). все таки склоняюсь ко второму варианту, через два запроса, ибо выводить нужно не все записи из таблицы, а по некоторому критерию. если вдруг у кого светлая мысль появится - вэлкам.
1) я не совсем точно выразился - там было обсуждение, что быстрее первый или второй способ получения общего количества записей: с count(*) или используя SQL_CALC_FOUND_ROWS. В обоих случаях нужно выполнять два запроса 2) общее число записей, удовлетворяющих запросу получается выполнением второго запроса $query="select FOUND_ROWS()"; причем сразу после выполнения первого с SQL_CALC_FOUND_ROWS В мануале в вольном переводе это звучит так Запрос на выборку записей может включать LIMIT для ограничения возвращаемых сервером записей. В некоторых случаях желательно знать, сколько записей будет возвращено без использования LIMIT, но без повторного исполнения запроса. Для получения этого числа включите SQL_CALC_FOUND_ROWS и затем вызовите FOUND_ROWS(): mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS(); Второй SELECT вернет количество записей, которое вернул бы первый SELECT если бы был написан без LIMIT