<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>З.П.И. &#187; Пагинатор</title>
	<atom:link href="http://wiki.dodex.org/tag/%d0%bf%d0%b0%d0%b3%d0%b8%d0%bd%d0%b0%d1%82%d0%be%d1%80/feed/" rel="self" type="application/rss+xml" />
	<link>http://wiki.dodex.org</link>
	<description>Что-то новое пришедшее в голову или интересное, найденное в интернете</description>
	<lastBuildDate>Tue, 08 Nov 2011 10:16:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Постраничная навигация</title>
		<link>http://wiki.dodex.org/2008/11/16/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f/</link>
		<comments>http://wiki.dodex.org/2008/11/16/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f/#comments</comments>
		<pubDate>Sun, 16 Nov 2008 09:26:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Дизайн]]></category>
		<category><![CDATA[навигация]]></category>
		<category><![CDATA[Пагинатор]]></category>
		<category><![CDATA[юзабилити]]></category>

		<guid isPermaLink="false">http://wiki.dodex.org/?p=43</guid>
		<description><![CDATA[Переключение страниц на сайтах, несомненно, является очень важной, концептуальной деталью. Поэтому реализовывать эту систему нужно очень внимательно, и с аккуратностью. Детали тут играют несравненно большую роль по сравнению с остальными компонентами дизайна. К сожалению, очень немногие люди пытаются сломать стереотипы, и продолжают творить нечто странное под видом навигации по страницам. Сегодня я постараюсь с вашей помощью решить эту ситуацию, чтобы сделать интернет лучше. Задачи [...]]]></description>
			<content:encoded><![CDATA[<p>Переключение страниц на сайтах, несомненно, является очень важной, концептуальной деталью. Поэтому реализовывать эту систему нужно очень внимательно, и с аккуратностью. Детали тут играют несравненно большую роль по сравнению с остальными компонентами дизайна.<a href="http://wiki.dodex.org/wp-content/uploads/2008/11/11.jpg"><img class="size-full wp-image-87 alignnone" src="http://wiki.dodex.org/wp-content/uploads/2008/11/11.jpg" alt="" width="400" height="150" /></a><a href="http://www.birzool.com/page-navigation/"> </a></p>
<p><span id="more-43"></span>К сожалению, очень немногие люди пытаются сломать стереотипы, и продолжают творить нечто странное под видом навигации по страницам. Сегодня я постараюсь с вашей помощью решить эту ситуацию, чтобы сделать интернет лучше.</p>
<h3>Задачи</h3>
<ol>
<li>Дать возможность в одно действие переключать страницу.</li>
<li>Удобный переход на последнюю и первую страницу.</li>
<li>Правильное переключение на следующую и предыдущую страницы.</li>
<li>Удобочитаемый вывод списка страниц.</li>
<li>Выделение активной страницы.</li>
<li>Сделать всё вышеперечисленное по возможности в простом и симпатичном виде.</li>
</ol>
<h3>Решение задач:</h3>
<p>Перед началом решения вышесказанных задач нужно определиться с тем, что нам нужно улучшать. Для этого перейдем на сайты, у которых есть навигация по страницам, и этих страниц явно больше 100. Для того, чтобы их найти, достаточно перейти в google и набрать поисковый запрос вида «719 720 721». После этого выбираем наиболее интересные примеры и изучаем их.</p>
<p>Я выбрал в качестве примеров недоработанной навигации по страницам следующие сайты:</p>
<p><strong>1. PhotoUA</strong><br />
Украинское агентство цифровой фотографии создано с целью предоставления цифрового новостного фото.</p>
<p><a href="http://www.photoua.com/"><img src="http://www.picamatic.com/show/2008/10/22/08/48/1224470_371x135.png" alt="Постраничная навигация" /></a></p>
<p>предоставлять пользователю удобную навигацию, так как страниц много, контента на страницах и того больше. Но, увы, этот сайт может представить только набор ошибок связанный с навигацией: невменяемые стрелочки, невозможность выбрать страницу, активная страница никак не выделяется, и др.</p>
<p><strong>2. </strong><strong>EuroLine</strong><br />
Довольно известная грузинская авиакомпания EuroLine предоставляет перелеты в Европу и Азию.</p>
<p><a href="http://www.avia24.com/"><img src="http://www.picamatic.com/show/2008/10/22/08/50/1224481_485x141.png" alt="Постраничная навигация" /></a></p>
<p>К сожалению, болезнь навигации не обошла и такую крупную компанию: переключение на страницы сделаны неудобно, переход на первую и последнюю страницу вовсе отсутствует, а ссылки на следующие и предыдущие страницы сделан в виде двойных стрелочек. К счастью, активная страница выделена.</p>
<p><strong>3. </strong><strong>Пресс-КIT</strong><br />
Украинское независимое агенство, предлагающее широкий спектр информационных, рекламных услуг, и разнообразные возможности фото-службы.</p>
<p><a href="http://www.kit.com.ua/"><img src="http://www.picamatic.com/show/2008/10/22/08/53/1224488_494x101.png" alt="Постраничная навигация" /></a></p>
<p>Увы и ах. Опять информационное агенство, которое должно дать возможность быстро путешествовать по страницам сайта, но… не дает. Более или менее интуитивные, стрелочки не позволяют быстро выбрать нужную страницу. Прибавьте к этому слабое выделение текущей страницы и возможности пролистать все сразу.</p>
<p><strong>4. </strong><strong>Форум посвященный Гарри Поттеру.</strong><br />
Кому-то может показаться смешным то, что я выбрал в качестве примера этот сайт, но должен вас разочаровать: выбрал я его потому, что он имеет огромное количество страниц.</p>
<p><a href="http://www.harrypotter.com.ua/"><img src="http://www.picamatic.com/show/2008/10/22/08/52/1224483_494x101.png" alt="Постраничная навигация" /></a></p>
<p>К сожалению, волшебные сайты не имеют иммунитета от болезни навигации и страдают большим количеством симптомов: не дают возможности интуитивно перейти на следующую\предыдущую страницу. Есть возможность перейти на нужный номер страницы, но, увы, очень корявая эта возможность.</p>
<p><strong>5. </strong><strong>Фишки.Нет</strong><br />
Аннотации за ненадобностью тут не будет. Все знают, что это за сайт и с чем его едят.</p>
<p><a href="http://www.fishki.net/"><img src="http://www.picamatic.com/show/2008/10/22/08/56/1224496_490x539.png" alt="Постраничная навигация" /></a></p>
<p>Этот сайт, по сути — кошмарный сон юзабилиста, но навигация по его страницам дает ему анти-фору еще больше. Судите сами: простой список из страниц. Более идиотского способа вывести почти 900 чисел найти сложно. При этом страницы расположены в шахматном порядке, что, по идее, должно было улучшить навигационные качества, но не улучшает. Активная страница выделяется, но банально теряется среди такого массива информации. Создатели сайта решили не делать ссылки на последнюю\первую страницы и на следующие\предыдущие. Видимо, посчитав их ненужными при возможности быстро (как им казалось) выбрать нужную пользователю страницу.</p>
<p>Итак, с проблемами мы разобрались. Теперь стоит перейти к решению поставленных нами задач.</p>
<p><strong>Дать возможность в одно действие переключать страницу</strong><br />
Под этой фразой я понимаю функцию быстрого выбора нужной страницы в 3 клика и меньше. Т.е. если пользователю нужно найти 761-ю страницу, не нужно его гонять по 10 страниц за раз. Нужно просто дать ему эту страницу выбрать.</p>
<p><img src="http://www.picamatic.com/show/2008/10/23/08/01/1230052_500x300.png" alt="Постраничная навигация" /></p>
<p>Решить эту ситуацию довольно просто: либо выпадающим списком с прокруткой (прокрутка для того, чтобы список был меньше чем 2000px при 1000 страницах), или же перемоткой списка движениями мыши. Тут всё зависит от личных предпочтений дизайнера. Лично я предпочитаю движения курсором. Что я подразумеваю под этим — смотрите на картинку сверху.</p>
<p><strong>Удобный переход на последнюю и первую страницу.</strong><br />
Если пользователь забрел вглубь сайта и хочет вернуться на первую страницу из списка, нужно дать ему способ сделать это быстро. По статистике, это одна из самых часто используемых функций навигации. Единственное ограничение в данном случае состоит в том, чтобы называть вещи своими именами и писать слова «Первая» и «Последняя» словами.</p>
<p>При этом желательно эти ссылки выводить полярно: “Первая” справа, “Последняя”слева .</p>
<p><img src="http://www.picamatic.com/show/2008/10/24/05/03/1235842_607x181.png" alt="Постраничная навигация" /></p>
<p>Также при создании этих ссылок учитывайте, что они не должны забирать внимание у ссылок «Следующая»/«Предыдущая» — ведь они самые важные в навигации по страницам.</p>
<p><strong>Правильное переключение на следующую и предыдущую страницы</strong><br />
Самый важный пункт списка. <span id="OutMsgText">По статистике, при наблюдении за пользователями, эти ссылки  используют чаще всего</span>. Именно поэтому они должны быть довольно большого размера (не огромного, но такого, чтобы пользователю не нужно было прицеливаться). Их не стоит представлять в виде одиночных стрелочек, как это любят делать создатели движков.</p>
<p><img src="http://www.picamatic.com/show/2008/10/24/05/04/1235848_607x181.png" alt="Постраничная навигация" /></p>
<p>Лучше всего совместить с помощью типографического форматирования стрелочку (они есть почти во всех стандартных шрифтах Windows) и надпись. Т.е. вот так: <a href="http://www.birzool.com/page-navigation/#">← Следующая</a> | <a href="http://www.birzool.com/page-navigation/#">Предыдущая →</a></p>
<p><strong>Удобочитаемый вывод списка страниц</strong><br />
Тут всё просто. Не стоит показывать массив из всех страниц сайта сразу. Пример сайта Фишки.Нет ясно показывает нам, что навигация по такому списку — не из легких. Лучше всего выводить 5-7 страниц, которые находятся по соседству.</p>
<p><img src="http://www.picamatic.com/show/2008/10/24/05/05/1235852_607x181.png" alt="Постраничная навигация" width="607" height="181" /></p>
<p>У некоторых людей существуют трудности с восприятием списка, если в нем находится больше семи элементов, поэтому выводить более семи соседних страниц не стоит.</p>
<p><strong>Выделение активной страницы</strong></p>
<p><img src="http://www.picamatic.com/show/2008/10/24/05/08/1235865_607x181.png" alt="Постраничная навигация" /></p>
<p>Принципы те же, что и для всех остальных ссылок. Чтобы человек быстро понял, где он находится, выделять активную страницу нужно также активно: полужирным начертанием, изменением цвета и, что немаловажно, стоит убирать ссылку с этой цифры. Ведь ссылаться на страницу, на который пользователь уже находится — плохой тон.</p>
<p><strong>Сделать всё вышеперечисленное в простом и симпатичном виде</strong><br />
Под этой фразой я подразумеваю отсутствие сложных графических эффектов, которые отвлекают внимание пользователя, и сложностей программных — глюков. Симпатичность вида каждый определяет для себя сам, но общие принципы еще никто не отменял: каждый элемент должен быть вровень относительно других, иметь размеры пропорциональные своим функциями. Также стоит соблюдать строгую графическую сетку и отступы от элементов.</p>
<p><img src="http://www.picamatic.com/show/2008/10/24/05/08/1235863_607x181.png" alt="Постраничная навигация" /></p>
<p><span id="OutMsgText">Результатом этого пункта у меня вышла вот такая вот  навигация. Все написанные выше принципы в ней соблюдаются. </span>Практическая реализация и способ решения в скором времени будут опубликованы в блоге Lampochek.Net, где я и еще один человек расскажем вам, как это всё делалось технически.</p>
<p><span>Автор: Ярослав Бирзул<br />
URL сайта: http://www.birzool.com</span></p>
]]></content:encoded>
			<wfw:commentRss>http://wiki.dodex.org/2008/11/16/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Постраничная навигация с MySQL при большом количестве записей</title>
		<link>http://wiki.dodex.org/2008/11/14/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f-%d1%81-mysql-%d0%bf%d1%80%d0%b8-%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be/</link>
		<comments>http://wiki.dodex.org/2008/11/14/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f-%d1%81-mysql-%d0%bf%d1%80%d0%b8-%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 14:23:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Пагинатор]]></category>
		<category><![CDATA[Производительность]]></category>

		<guid isPermaLink="false">http://wiki.dodex.org/?p=36</guid>
		<description><![CDATA[Рано или поздно многие крупные проекты сталкиваются с проблемами производительности при постраничной навигации по записям. Некоторые из них решают эту проблему ограничением количества доступных для просмотра записей (скажем, не больше 1000). Вполне приемлемое решение. Но в этом случаем могут возникнуть проблемы с индексированием сайта сторонними поисковиками, которые и представляют наибольшую угрозу. В этой статье я [...]]]></description>
			<content:encoded><![CDATA[<p>Рано или поздно многие крупные проекты сталкиваются с проблемами производительности при постраничной навигации по записям. Некоторые из них решают эту проблему ограничением количества доступных для просмотра записей (скажем, не больше 1000). Вполне приемлемое решение. Но в этом случаем могут возникнуть проблемы с индексированием сайта сторонними поисковиками, которые и представляют наибольшую угрозу. В этой статье я хотел бы отказаться от привычной для всех панели навигации вида «1..2..3..4..» в пользу простой «вперед… назад» (будет проще объяснить), но это не проблема реализовать подобное и с первым вариантом.<span id="more-36"></span><br />
Более точно определить тему, назвав, какое количество записей считать достаточно большим для появления тормозов, не получится, так как эта цифра для всех разная и сильно зависит от того, насколько быстрые у Вас жесткие диски, сколько памяти, и какая часть Ваших данных уже закеширована в ней и тд. Но если Вы и Ваши сервера ощущают, что n-ная страница при выводе даётся тяжелее первой, и при этом не знаете, что с этим делать – статья для Вас. Но для начала, я хотел бы на пальцах объяснить, почему ОНО работает медленно.</p>
<p>Кстати, тест происходит на виртуальной машинке, работаю я с СУБД под рутом, версия MySQL – 5.0.32.<br />
<a name="habracut"></a></p>
<h4>1 Начнем с данных</h4>
<p>Для тестирования создадим небольшую табличку и наполним ее чем-нибудь.</p>
<p><code>CREATE TABLE items (<br />
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,<br />
height INT UNSIGNED NOT NULL DEFAULT 0,<br />
width INT UNSIGNED NOT NULL DEFAULT 0,<br />
price DECIMAL(10,2) NOT NULL DEFAULT 0.0,<br />
title VARCHAR(255) NOT NULL<br />
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;<br />
</code></p>
<p>Небольшим скриптом на PHP был сгенерирован INSERT 100000 записей. Данные такого вида:<br />
— порядок полей в INSERT:<br />
height, width, price, title<br />
— шаблон для полей:<br />
$val_tmpl = &#8220;\t(%d, %d, %f, &#8216;Item %d&#8217;)&#8221;;<br />
— тестовые значения ($i = 1..100000):<br />
sprintf($val_tmpl, rand(0, 120), rand(0, 220), 10 * rand(0, $i) / $i, $i);</p>
<p>Заносим это все в нашу БД. И можно начинать…</p>
<h4>2 Обычный метод постраничного вывода</h4>
<p>Все, кто уже знает, чем плохи COUNT(*) и LIMIT… OFFSET, могут пропустить эту часть.</p>
<p>Прежде, чем рисовать навигатор, мы делаем SELECT COUNT(*) … WHERE (условия_выборки). Многие, почему-то уверены, что даже если у нас миллионы записей, но условия_выборки позволяют использовать индекс, то такой запрос отработает очень быстро. Проведем эксперимент. Выберем количество записей, у которых height больше 100. Для начала посмотрим, что будет, если индекса по полю height нет.</p>
<p>FLUSH STATUS;</p>
<p>SELECT SQL_NO_CACHE COUNT(*) FROM items WHERE height&gt;100;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
| 16405 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.09 sec)</p>
<p>SHOW STATUS LIKE ‘handler%’;</p>
<p>Последняя команда покажет, сколько же, и каких действий пришлось сделать СУБД, чтобы выполнить наш запрос. Так как индекса у нас нет, MySQL пришлось читать данные прямо из таблицы, поэтому нас интересует строка:<br />
…<br />
| Handler_read_rnd_next | 100001 |<br />
…</p>
<p>То есть, MySQL пришлось сделать 100001 операцию перехода к следующей записи, чтобы найти все, соответствующие запросу.</p>
<p>Везде ниже перед каждым SELECT подразумевается выполнение FLUSH STATUS, а после: SHOW STATUS LIKE ‘handler%’.</p>
<p>Чем нам может помочь индекс.</p>
<p>ALTER TABLE items ADD INDEX height_idx (height);</p>
<p>SELECT SQL_NO_CACHE COUNT(*) FROM items FORCE INDEX(height_idx) WHERE height&gt;100;<br />
+&#8212;&#8212;&#8212;-+<br />
| count(*) |<br />
+&#8212;&#8212;&#8212;-+<br />
| 16405 |<br />
+&#8212;&#8212;&#8212;-+<br />
1 row in set (0.04 sec)</p>
<p>В данном случае использовался индекс, поэтому Handler_read_rnd_next будет равен 0, а вот<br />
…<br />
| Handler_read_next | 16405 |<br />
…<br />
То есть индекс позволяет изначально посчитать только те записи, которые нужны, НО ему все равно требуется пробежаться по ним всем. Нет никакой магии, MySQL нигде не хранит количество записей, соответствующих запросу. Поэтому, если у вас миллионы записей, соответствующих условиям запроса, COUNT будет работать очень медленно.</p>
<p>Второй момент. LIMIT … OFFSET. Тот же эксперимент. Попросим нам 5 записей.</p>
<p>SELECT SQL_NO_CACHE * FROM items FORCE INDEX(height_idx) WHERE height&gt;100 LIMIT 5;<br />
…<br />
5 rows in set (0.00 sec)<br />
…<br />
| Handler_read_next | 4 |<br />
…<br />
Вроде все логично. А теперь попросим вернуть другие 5 записей, начиная с 16401.</p>
<p>SELECT SQL_NO_CACHE * FROM items FORCE INDEX(height_idx) WHERE height&gt;100 LIMIT 16400, 5;<br />
…<br />
5 rows in set (0.13 sec)</p>
<p>Видим, что время выборки значительно возросло. Смотрим статус:<br />
…<br />
| Handler_read_next | 16404 |<br />
…<br />
То есть, MySQL, прочитал все 16405, а только потом просто откинул все ненужные.<br />
Как быть?</p>
<h4>3 Как быть</h4>
<p>Итак. От нас требуется вывести 10 записей, а так же нарисовать меню навигации. Мы поняли, что, чтобы дойти до записи, с которой необходимо начать отдавать нам результаты, MySQL тратит много лишних действий. Единственное, как это избежать – сразу перейти к нужной, изменив условия выборки.<br />
Рассмотрим все на простом примере: пусть записи выдаются отсортированные по id. В этом случае нам нужно вместе со ссылкой передать id записи, на которой мы остановились. А остановимся мы на записи с id=10. То есть, в параметрах ссылки на следующую страницу нам нужно передать 10. Соответственно, для второй страницы запрос будет выглядеть так:</p>
<p>SELECT SQL_NO_CACHE id FROM items WHERE id&gt;10 ORDER BY id LIMIT 10;</p>
<p>Кстати, в обоих случаях Handler_read_next будет равен 9. То есть, прыгнули на первую соответствующую запросу запись (благодаря индексу) и сделали 9 переходов на следующую. Самое главное, что какое бы число вместо 10 в условие мы не подставили – мы всегда в результате SHOW STATUS увидим одно и то же, и время выполнения такого запроса уже не будет зависеть от того, где мы находимся, а будет зависеть только от того, сколько и чего мы выбираем.<br />
Надеюсь, смысл Вам понятен. Давайте тогда решим, что делать с меню навигации, а потом перейдем к более сложной ситуации. Пусть в url мы используем ключевые слова next, previous и last. В каких случаях показывать ссылки «вперед», «назад» и «последняя»?<br />
Каждый раз, когда нам приходит next (запрос следующей страницы), мы выбираем не 10 записей, а 11, начиная с id, переданного в параметрах запроса. Если нам вернулось 11 записей, то следует показать ссылку вперед с id 10-й записи, а 11-ю откинуть. Если вернулось меньше 11 записей, то ссылку вперед показывать не надо. При этом мы всегда (всегда, когда пришло next) показываем ссылку назад (previous) с id первой записи из выборки. Ссылки «в начало» и «последняя» всегда показываются вместе с «назад» и «вперед» соответственно. То есть, если мы решили показывать «назад», то должны показать и «в начало».<br />
Каждый раз, когда нам приходит previous (запрос на предыдущую страницу), мы выбираем 11 записей, у которых id меньше указанного в запросе, отсортированные в обратном порядке. То же самое: если вернулось 11 записей, то ссылку «назад» показываем. Ссылку вперед показываем всегда.<br />
Надеюсь, понятно написал…<br />
Что если нам пришел запрос «last»? Просто показать 10 записей, начиная с самой последней. То есть:</p>
<p>SELECT id FROM items ORDER BY id DESC LIMIT 10;</p>
<p>Думаете, у кого-нибудь из пользователей хватит сил промотать несколько сотен, а то и тысяч страниц, для того, чтобы обвинить Вас во лжи, обнаружив в итоге на первой странице не 10 записей? Даже если и хватит, то Вы можете ответить, что он слишком долго мотал…</p>
<p>Предыдущий пример был прост тем, что id – уникален. А что если требуется сортировка по полю, значения которого могут повторяться? Например, height в нашем случае. Простым запросом было выяснено, что в таблице каждое значения height встречается примерно 800 раз. Просто передать последний выведенный height в параметрах запроса уже мало. Поможет нам всё тот же id. От нас просят отсортировать записи по высоте, но это ведь не мешает нам отсортировать их потом еще и по id?<br />
Для этого нам понадобится новый индекс:</p>
<p>ALTER TABLE items ADD KEY height_id_idx (height, id);</p>
<p>Запрос для первой страницы будет такой:</p>
<p>SELECT SQL_NO_CACHE id, height FROM items ORDER BY height, id LIMIT 10;</p>
<p>В моих результатах у последней записи height=0, id=1174. Так и надо передать следующей странице. Например, next_0_1174 или next/0/1074 – как Вам удобнее.<br />
Теперь нам нужно выбрать записи, у которых либо height больше 0, либо height=0, а id&gt;1174 (именно для этого мы и сделали дополнительную сортировку).<br />
То есть:</p>
<p>SELECT SQL_NO_CACHE * FROM items WHERE (height&gt;0) OR (height=0 AND id&gt;1174) ORDER BY height, id LIMIT 10;</p>
<p>Надеюсь, пояснять, почему так, не нужно. Статус по-прежнему показывает всего 9 шагов вперед.<br />
Таким образом, мы можем добавлять и другие сортировки. Например, если мы хотим вывести все записи, отсортированные по цене и высоте, запрос будет таким:</p>
<p>SELECT SQL_NO_CACHE * FROM items WHERE (price&gt;5) OR (price=5 AND height&gt;0) AND (price=5 AND height=0 AND id&gt;1174) ORDER BY price, height, id LIMIT 10;</p>
<p>Остается только передавать все необходимые данные, правильно их обрабатывать и подставлять в запрос. И про индекс не забудьте.</p>
<h4>4 Что делать с количеством результатов</h4>
<p>Как быть, если мы хотим показать пользователям, сколько же результатов найдено? Так как речь идет о больших числах, то вряд ли нас кто-то будет проверять. Тот же гугл может выдать, что нашел 1000000 страниц, соответствующих запросу, но больше 1000 вы не увидите. Мы тоже можем выдать количество результатов лишь примерно. Где его взять и как оценить? Помните, мы выполняли запрос:</p>
<p>SELECT SQL_NO_CACHE COUNT(*) FROM items FORCE INDEX(height_idx) WHERE height&gt;100;</p>
<p>А давайте сделаем так:<br />
EXPLAIN SELECT SQL_NO_CACHE * FROM items FORCE INDEX(height_idx) WHERE height&gt;100;</p>
<p>В результате получим что-то такое:<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;-+<br />
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;-+<br />
| 1 | SIMPLE | items | range | height_idx | height_idx | 4 | NULL | 22616 | Using where |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;-+</p>
<p>Столбец rows как раз показывает оценочное число записей, которые нужно просмотреть. 22616 и 16405 – разница совсем не велика. Можно округлить до ~20000, да и ладно. Сойдёт. Только помните, что если используете, например, подзапросы и/или объединения, то EXPLAIN вернет несколько строк. Их все надо прочитать и перемножить значения rows.</p>
<h4>Заключение</h4>
<p>Данная проблема уже освещалась вскользь на хабре, но не так подробно.<br />
Статья получилась больше, чем ожидал, хотя текст и разбавлен вставками запросов и результатов. В данный момент некуда выложить использованный для генерации данных скрипт + sql файлы. В общем… На заключение сил не осталось:)</p>
<p><em>Источник: http://habrahabr.ru/blogs/mysql/44608/</em></p>
]]></content:encoded>
			<wfw:commentRss>http://wiki.dodex.org/2008/11/14/%d0%bf%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%bd%d0%b0%d1%8f-%d0%bd%d0%b0%d0%b2%d0%b8%d0%b3%d0%b0%d1%86%d0%b8%d1%8f-%d1%81-mysql-%d0%bf%d1%80%d0%b8-%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

