<?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>Ars Longa, Vita Brevis &#187; MySQL</title>
	<atom:link href="http://blog.sjinks.pro/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sjinks.pro</link>
	<description>Quod scripsi, scripsi</description>
	<lastBuildDate>Mon, 06 Feb 2012 17:56:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Блокировки транзакций InnoDB при удалении данных из таблицы</title>
		<link>http://blog.sjinks.pro/mysql/889-lock-wait-timeout-exceeded-try-restarting-transaction/</link>
		<comments>http://blog.sjinks.pro/mysql/889-lock-wait-timeout-exceeded-try-restarting-transaction/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 16:01:16 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[оптимизация]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=889</guid>
		<description><![CDATA[Lock wait timeout exceeded; try restarting transaction Ситуация: есть несколько физических почтовых серверов (PowerMTA), отсылающих более четырёх миллионов сообщений в сутки. Есть виртуальный сервер базы данных (причём не очень мощный), на котором крутится MySQL с InnoDB; в базу данных пишутся логи доставки/не доставки сообщений и ведётся статистика по IP-адресам, VMTA и доменам. Попутно выполняется классификация и [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/889-lock-wait-timeout-exceeded-try-restarting-transaction/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Lock wait timeout exceeded; try restarting transaction</em></h2>
<p>Ситуация: есть несколько физических почтовых серверов (PowerMTA), отсылающих более четырёх миллионов сообщений в сутки. Есть виртуальный сервер базы данных (причём не очень мощный), на котором крутится <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> с <a href="http://blog.sjinks.pro/tag/innodb/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  InnoDB">InnoDB</a>; в базу данных пишутся логи доставки/не доставки сообщений и ведётся статистика по IP-адресам, VMTA и доменам. Попутно выполняется классификация и анализ hard и soft bounces. База за день увеличивается примерно на 5 гигабайт. Часть логов недельной давности удаляется.<span id="more-889"></span></p>
<p>Так как с базой (на запись) работает несколько клиентов, структура таблиц/индексы выбраны таким образом, чтобы обеспечить максимальную скорость добавления записей и минимум блокировок.</p>
<p>Проблема возникла с ведением статистики.</p>
<p>Есть таблица такой структуры:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p8894">
        <div class="code mysql" id="p889code4">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="kw15">log</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; id <span class="kw4">BIGINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw1">PRIMARY KEY</span> <span class="kw6">AUTO_INCREMENT</span><span class="sy2">,</span><br />
&nbsp; &nbsp; ymd <span class="kw4">INTEGER</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; domain <span class="kw4">VARCHAR</span><span class="br0">&#40;</span>255<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; vmta <span class="kw4">VARCHAR</span><span class="br0">&#40;</span>255<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; ip <span class="kw4">VARCHAR</span><span class="br0">&#40;</span>45<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; deliveries <span class="kw4">TINYINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; bounces <span class="kw4">TINYINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; transients <span class="kw4">TINYINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; pmta_bounces <span class="kw4">TINYINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><br />
<span class="br0">&#41;</span> <span class="kw1">ENGINE</span><span class="sy1">=</span><span class="kw1">InnoDB</span> <span class="kw2">DEFAULT</span> <span class="kw7">CHARSET</span><span class="sy1">=</span>utf8<span class="sy2">;</span>
        </div>
    </div>
</div>

<p>В таблицу заносятся данные о доставке сообщений — выполняется это триггерами post insert: при доставке сообщения в таблицу заносится запись <span class="codebox"><code class="mysql"><span class="br0">&#40;</span><span class="kw3">NULL</span><span class="sy2">,</span> <span class="kw17">DATE_FORMAT</span><span class="br0">&#40;</span><span class="kw17">NOW</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;<span class="es1">%</span>Y<span class="es1">%</span>m<span class="es1">%</span>d&quot;</span><span class="br0">&#41;</span><span class="sy2">,</span> domain<span class="sy2">,</span> vmta<span class="sy2">,</span> ip<span class="sy2">,</span> <span class="nu0">1</span><span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">0</span><span class="br0">&#41;</span></code></span>, при получении hard bounce — <span class="codebox"><code class="mysql"><span class="br0">&#40;</span><span class="kw3">NULL</span><span class="sy2">,</span> <span class="kw17">DATE_FORMAT</span><span class="br0">&#40;</span><span class="kw17">NOW</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;<span class="es1">%</span>Y<span class="es1">%</span>m<span class="es1">%</span>d&quot;</span><span class="br0">&#41;</span><span class="sy2">,</span> domain<span class="sy2">,</span> vmta<span class="sy2">,</span> ip<span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">1</span><span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">0</span><span class="sy2">,</span> <span class="nu0">0</span><span class="br0">&#41;</span></code></span> — всё это выполняется довольно быстро, жалоб нет.</p>
<p>Проблемы начинаются при обработке данного лога. Что нужно сделать: подсчитать SUM(deliveries), SUM(bounces), SUM(transients), SUM(pmta_bounces) для каждой четвёрки (ymd, domain, vmta, ip). Данная операция выполняется каждые десять минут. Обработанные данные из таблицы log нужно удалить.</p>
<p>В терминах SQL это выглядит примерно так:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p8895">
        <div class="code mysql" id="p889code5">
<span class="kw1">CREATE</span> <span class="kw1">PROCEDURE</span> populate_stats_daily<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">BEGIN</span><br />
&nbsp; &nbsp; <span class="kw1">DECLARE</span> max_id <span class="kw4">BIGINT</span> <span class="kw6">UNSIGNED</span><span class="sy2">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">START</span> <span class="kw1">TRANSACTION</span><span class="sy2">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">SELECT</span> <span class="kw22">MAX</span><span class="br0">&#40;</span>id<span class="br0">&#41;</span> <span class="kw1">INTO</span> max_id <span class="kw1">FROM</span> <span class="kw15">log</span><span class="sy2">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">INSERT</span> <span class="kw1">INTO</span> stats_daily <span class="br0">&#40;</span>ymd<span class="sy2">,</span> domain<span class="sy2">,</span> vmta<span class="sy2">,</span> ip<span class="sy2">,</span> deliveries<span class="sy2">,</span> bounces<span class="sy2">,</span> transients<span class="sy2">,</span> pmta_bounces<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">SELECT</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ymd<span class="sy2">,</span> domain<span class="sy2">,</span> vmta<span class="sy2">,</span> ip<span class="sy2">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw22">SUM</span><span class="br0">&#40;</span>deliveries<span class="br0">&#41;</span> <span class="kw1">AS</span> deliveries<span class="sy2">,</span> <span class="kw22">SUM</span><span class="br0">&#40;</span>bounces<span class="br0">&#41;</span> <span class="kw1">AS</span> bounces<span class="sy2">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw22">SUM</span><span class="br0">&#40;</span>transients<span class="br0">&#41;</span> <span class="kw1">AS</span> transients<span class="sy2">,</span> <span class="kw22">SUM</span><span class="br0">&#40;</span>pmta_bounces<span class="br0">&#41;</span> <span class="kw1">AS</span> pmta_bounces<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">FROM</span> <span class="kw15">log</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">WHERE</span> id <span class="sy1">&lt;=</span> max_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">GROUP BY</span> ymd<span class="sy2">,</span> domain<span class="sy2">,</span> vmta<span class="sy2">,</span> ip<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">ORDER BY</span> <span class="kw3">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">ON</span> <span class="kw1">DUPLICATE KEY</span> <span class="kw1">UPDATE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deliveries &nbsp; <span class="sy1">=</span> deliveries <span class="sy1">+</span> <span class="kw1">VALUES</span><span class="br0">&#40;</span>deliveries<span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bounces &nbsp; &nbsp; &nbsp;<span class="sy1">=</span> bounces <span class="sy1">+</span> <span class="kw1">VALUES</span><span class="br0">&#40;</span>bounces<span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transients &nbsp; <span class="sy1">=</span> transients <span class="sy1">+</span> <span class="kw1">VALUES</span><span class="br0">&#40;</span>transients<span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pmta_bounces <span class="sy1">=</span> pmta_bounces <span class="sy1">+</span> <span class="kw1">VALUES</span><span class="br0">&#40;</span>pmta_bounces<span class="br0">&#41;</span><span class="sy2">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">DELETE</span> <span class="kw1">FROM</span> <span class="kw15">log</span> <span class="kw1">WHERE</span> id <span class="sy1">&lt;=</span> max_id<span class="sy2">;</span><br />
&nbsp; &nbsp; <span class="kw1">COMMIT</span><span class="sy2">;</span><br />
<span class="kw12">END</span>
        </div>
    </div>
</div>

<p>Проблема наступает при выполнении оператора <code>DELETE</code>: <code>SHOW PROCESSLIST</code> показывает состояние <code>Updating</code> минуты полторы, после чего в <a href="http://blog.sjinks.pro/tag/log/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  лог">лог</a> пишется печально известное сообщение <strong>Lock wait timeout exceeded; try restarting transaction</strong> и транзакция откатывается. При этом количество записей в таблице <code>log</code> всего лишь порядка 80,000.</p>
<p>В принципе, проблема с <code>DELETE</code> <a href="http://www.google.ru/search?q=InnoDB+slow+delete">давно известна</a>: в InnoDB удаление строк весьма тормозное. По всей видимости, это усугубляется тем, что в таблицу постоянно идёт запись новых данных. Руководство пользователя <a href="http://dev.mysql.com/doc/refman/5.1/en/innodb-locks-set.html">объясняет</a> суть проблемы.</p>
<p>А решение таково: заводим дополнительную колонку в таблице (<code>processed</code>) и создаём по ней индекс. <code>DELETE FROM log WHERE id <= max_id</code> заменяем на <code>UPDATE log SET processed = 1 WHERE id <= max_id</code>, что выполняется гораздо быстрее. Затем заводим еще одну транзакцию, в которой удаляем строки с <code>processed = 1</code>.</p>
<p>Но в один заход все строки удалить не получится, поэтому придётся идти на хитрость:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p8896">
        <div class="code mysql" id="p889code6">
<span class="kw1">BEGIN</span><br />
&nbsp; &nbsp; <span class="kw1">DECLARE</span> cnt <span class="kw4">BIGINT</span> <span class="kw6">UNSIGNED</span><span class="sy2">;</span><br />
<br />
<span class="coMULTI">/* ... */</span><br />
<br />
&nbsp; &nbsp; <span class="kw13">REPEAT</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">START</span> <span class="kw1">TRANSACTION</span><span class="sy2">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">DELETE</span> <span class="kw1">FROM</span> <span class="kw15">log</span> <span class="kw1">WHERE</span> processed <span class="sy1">=</span> 1 <span class="kw1">LIMIT</span> <span class="nu0">1000</span><span class="sy2">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">SELECT</span> <span class="kw23">ROW_COUNT</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">INTO</span> cnt<span class="sy2">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">COMMIT</span><span class="sy2">;</span><br />
&nbsp; &nbsp; UNTIL cnt <span class="sy1">=</span> 0 <span class="kw12">END</span> <span class="kw13">REPEAT</span><span class="sy2">;</span><br />
<span class="kw12">END</span>
        </div>
    </div>
</div>

<p>Смысл в том, что удаление производится небольшими кусками (что будет относительно быстро); каждое удаление выполняется в своей транзакции (в случае блокировки транзакции в хвосте таблицы большая часть записей будет удалена, что не так плохо).</p>
<p>Вполне возможно, что можно обойтись без дополнительной колонки и использовать <code>REPEAT … END REPEAT</code> с <code>DELETE FROM log WHERE id <= max_id</code>, но текущий вариант работает, кушать не просит, блокировок не создаёт. А наше основное правило — <span title="if it ain't broke, don't fix it">si fractum non sit, noli id reficere</span>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/889-lock-wait-timeout-exceeded-try-restarting-transaction/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/889-lock-wait-timeout-exceeded-try-restarting-transaction/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Подсчёт трафика в nginx: часть 2</title>
		<link>http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/</link>
		<comments>http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 01:12:27 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Администрирование]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[лог]]></category>
		<category><![CDATA[трафик]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=502</guid>
		<description><![CDATA[Дальнейшие усовершенствования процесса В статье «Подсчёт трафика в nginx» я приводил один из возможных вариантов живого подсчёта трафика в nginx. У прошлого решения есть недостатки: используется три лишних процесса; используется много файловых дескрипторов (зависит от количества виртуальных хостов). Я на днях нашёл еще один вариант. Будем использовать немного другую структуру таблицы: CREATE TABLE `traf_stats` ( [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Дальнейшие усовершенствования процесса</em></h2>
<p>В статье «<strong><a href="http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/">Подсчёт трафика в nginx</a></strong>» я приводил один из возможных вариантов <em>живого</em> подсчёта трафика в <a href="http://blog.sjinks.pro/tag/nginx/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  nginx">nginx</a>.</p>
<p>У прошлого решения есть недостатки:</p>
<ul>
<li>используется три лишних процесса;</li>
<li>используется много файловых дескрипторов (зависит от количества виртуальных хостов).</li>
</ul>
<p>Я на днях нашёл еще один вариант.<span id="more-502"></span></p>
<p>Будем использовать немного другую структуру таблицы:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50213">
        <div class="code mysql" id="p502code13">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`traf<span class="es1">_</span>stats`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`in`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`out`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`host`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span>64<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`dt`</span> <span class="kw4">MEDIUMINT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><br />
<span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>Основное отличие — не используются поля, которые легко вычислить (<span class="codebox"><code class="mysql"><span class="st0">`sum`</span> <span class="sy1">=</span> <span class="st0">`in`</span> <span class="sy1">+</span> <span class="st0">`out`</span></code></span>, <span class="codebox"><code class="mysql"><span class="st0">`ym`</span> <span class="sy1">=</span> <span class="kw17">EXTRACT</span><span class="br0">&#40;</span><span class="kw8">YEAR_MONTH</span> <span class="kw1">FROM</span> <span class="st0">`dt`</span><span class="br0">&#41;</span></code></span>) и отсутствуют индексы (ибо при высокой посещаемости сжимать таблицу на живую — это самоубийство чистой воды).</p>
<p>Переходим к магии.<br />
Создаём <a href="http://blog.sjinks.pro/tag/log/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  лог">лог</a>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50214">
        <div class="code bash" id="p502code14">
<span class="kw2">mkfifo</span> <span class="re5">--mode</span>=0666 <span class="sy0">/</span>var<span class="sy0">/</span>log<span class="sy0">/</span>nginx<span class="sy0">/</span>traffic.log
        </div>
    </div>
</div>

<p>А далее, если Вы хорошо знакомы с программированием под <a href="http://blog.sjinks.pro/tag/linux/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Linux">Linux</a>/<a href="http://blog.sjinks.pro/tag/unix/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  UNIX">Unix</a>, наверное, догадались: во <strong>все</strong> виртуальные хосты прописываем</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50215">
        <div class="code text" id="p502code15">
access_log &nbsp;/var/log/nginx/traffic.log &nbsp;trafctr;
        </div>
    </div>
</div>

<p>Формат <code>trafctr</code> определён следующим образом (извращение):</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50216">
        <div class="code text" id="p502code16">
log_format trafctr 'INSERT DELAYED INTO traf_stats VALUES($request_length, $bytes_sent, &quot;$server_name&quot;, UNIX_TIMESTAMP(STR_TO_DATE(SUBSTR(&quot;$time_local&quot;, 1, 20), CONCAT(CHAR(37), &quot;d/&quot;, CHAR(37), &quot;b/&quot;, CHAR(37), &quot;Y:&quot;, CHAR(37), &quot;H:&quot;, CHAR(37), &quot;i:&quot;, CHAR(37), &quot;s&quot;))));';
        </div>
    </div>
</div>

<p>Фактически, в pipe будет писаться такой запрос:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50217">
        <div class="code mysql" id="p502code17">
<span class="kw2">INSERT</span> <span class="kw1">DELAYED</span> <span class="kw1">INTO</span> traf_stats <span class="kw1">VALUES</span><br />
<span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="nu0">123</span><span class="sy2">,</span> <br />
&nbsp; &nbsp; <span class="nu0">456</span><span class="sy2">,</span> <br />
&nbsp; &nbsp; <span class="st0">&quot;myserver.com&quot;</span><span class="sy2">,</span> <br />
&nbsp; &nbsp; <span class="kw17">UNIX_TIMESTAMP</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw17">STR_TO_DATE</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SUBSTR<span class="br0">&#40;</span><span class="st0">&quot;18/Feb/2009:17:24:37 -0500&quot;</span><span class="sy2">,</span> 1<span class="sy2">,</span> 20<span class="br0">&#41;</span><span class="sy2">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw13">CONCAT</span><span class="br0">&#40;</span><span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;d/&quot;</span><span class="sy2">,</span> <span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;b/&quot;</span><span class="sy2">,</span> <span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;Y:&quot;</span><span class="sy2">,</span> <span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;H:&quot;</span><span class="sy2">,</span> <span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;i:&quot;</span><span class="sy2">,</span> <span class="kw14">CHAR</span><span class="br0">&#40;</span><span class="nu0">37</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">&quot;s&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#41;</span><br />
<span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p><span class="codebox"><code class="mysql">SUBSTR<span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> убирает хвост в виде часового пояса, <span class="codebox"><code class="mysql"><span class="kw17">STR_TO_DATE</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> используется для создания строки с временем, которую поймёт <span class="codebox"><code class="mysql"><span class="kw17">UNIX_TIMESTAMP</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span>, а <span class="codebox"><code class="mysql"><span class="kw13">CONCAT</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span>… Что же, <span class="codebox"><code class="mysql"><span class="kw13">CONCAT</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> нужен, чтобы nginx не ругался на строки вида <code>%d/%b/%Y:%H:%i:%s</code>. Не любит <code>nginx</code> знак процента.</p>
<p>Как данные попадают в базу? Всё просто:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p50218">
        <div class="code bash" id="p502code18">
mysql <span class="re5">-uuser</span> <span class="re5">-ppass</span> <span class="re5">-Ddatabase</span> <span class="re5">--batch</span> <span class="re5">--force</span> <span class="sy0">&lt;</span> <span class="sy0">/</span>var<span class="sy0">/</span>log<span class="sy0">/</span>nginx<span class="sy0">/</span>traffic.log
        </div>
    </div>
</div>

<p>Следующий этап (часть 3): написание демона, заменяющего <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">mysql</a> (как процесс). Демон будет сжимать данные на лету и передавать их <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a>-серверу. Благодаря этому мы снизим нагрузку на <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> (запросы будут передаваться в виде extended insert, а сами данные уже будут просуммированы).</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Подсчет трафика в nginx</title>
		<link>http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/</link>
		<comments>http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 01:13:55 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Администрирование]]></category>
		<category><![CDATA[лог]]></category>
		<category><![CDATA[трафик]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=488</guid>
		<description><![CDATA[О большой практической пользе awk Постановка задачи: есть Linux-сервер, на котором живёт сотня-другая виртуальных хостов. Сервер работает под управлением nginx. Нужно реализовать подсчет трафика с отображением «живой» статистики. Вариант решения: Таблица для хранения данных: CREATE TABLE `traf_stats` ( `in` INTEGER UNSIGNED NOT NULL, /* если качаются файлы размером более 4 ГБ, нужно использовать BIGINT */ [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>О большой практической пользе awk</em></h2>
<p><strong>Постановка задачи:</strong> есть <a href="http://blog.sjinks.pro/tag/linux/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Linux">Linux</a>-сервер, на котором живёт сотня-другая виртуальных хостов. Сервер работает под управлением <a href="http://blog.sjinks.pro/tag/nginx/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  nginx">nginx</a>. Нужно реализовать подсчет трафика с отображением «живой» статистики.<span id="more-488"></span></p>
<p><strong>Вариант решения:</strong></p>
<p>Таблица для хранения данных:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48824">
        <div class="code mysql" id="p488code24">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`traf<span class="es1">_</span>stats`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`in`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span> <span class="coMULTI">/* если качаются файлы размером более 4 ГБ, нужно использовать BIGINT */</span><br />
&nbsp; &nbsp; <span class="st0">`out`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`sum`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`host`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span>64<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`dt`</span> <span class="kw4">DATETIME</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="st0">`ym`</span> <span class="kw4">MEDIUMINT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; &nbsp; <span class="kw1">KEY</span> <span class="st0">`host<span class="es1">_</span>ym`</span><span class="br0">&#40;</span><span class="st0">`host`</span><span class="sy2">,</span> <span class="st0">`ym`</span><span class="br0">&#41;</span><br />
<span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>Фрагменты конфигурационного файла nginx:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48825">
        <div class="code text" id="p488code25">
http {<br />
&nbsp; &nbsp; log_format trafctr '$request_length $bytes_sent $server_name $time_local';<br />
}
        </div>
    </div>
</div>

<p>Каждый виртуальный хост должен содержать подобную строку:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48826">
        <div class="code text" id="p488code26">
server {<br />
&nbsp; &nbsp; access_log /var/log/nginx/traffic_vhost trafctr;<br />
}
        </div>
    </div>
</div>

<p>В логе будут записи вида</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48827">
        <div class="code text" id="p488code27">
1761 484 example.com 22/Jan/2009:20:05:46 -0500
        </div>
    </div>
</div>

<p>А теперь собственно чёрная магия с использованием <span class="codebox"><code class="bash"><span class="kw2">awk</span></code></span>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48828">
        <div class="code bash" id="p488code28">
<span class="co0">#! /bin/sh</span><br />
<br />
<span class="re2">AWK</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>bin<span class="sy0">/</span><span class="kw2">awk</span><br />
<span class="re2">TAIL</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>bin<span class="sy0">/</span><span class="kw2">tail</span><br />
<span class="re2">MYSQL</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>bin<span class="sy0">/</span>mysql<br />
<span class="re2">MYSQL_USER</span>=mysql<br />
<span class="re2">MYSQL_PASS</span>=pass<br />
<span class="re2">MYSQL_DB</span>=traffic<br />
<span class="re2">LOG_PATH</span>=<span class="sy0">/</span>var<span class="sy0">/</span>log<span class="sy0">/</span>nginx<br />
<br />
<span class="re1">$TAIL</span> <span class="re5">-F</span> <span class="re1">$LOG_PATH</span><span class="sy0">/*</span> <span class="sy0">|</span> <span class="re1">$AWK</span> <span class="st_h">'<br />
/^[[:digit:]]+ [[:digit:]]+ / {<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Jan&quot;]=&quot;01&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Feb&quot;]=&quot;02&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Mar&quot;]=&quot;03&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Apr&quot;]=&quot;04&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;May&quot;]=&quot;05&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Jun&quot;]=&quot;06&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Jul&quot;]=&quot;07&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Aug&quot;]=&quot;08&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Sep&quot;]=&quot;09&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Oct&quot;]=&quot;10&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Nov&quot;]=&quot;11&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m[&quot;Dec&quot;]=&quot;12&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; year=substr($4, 8, 4);<br />
&nbsp; &nbsp; &nbsp; &nbsp; month=m[substr($4, 4, 3)];<br />
&nbsp; &nbsp; &nbsp; &nbsp; day=substr($4, 1, 2);<br />
&nbsp; &nbsp; &nbsp; &nbsp; print &quot;INSERT INTO traf_stats VALUES (&quot; $1 &quot;, &quot; $2 &quot;, &quot; $1+$2 &quot;, \&quot;&quot; $3 &quot;\&quot;, \&quot;&quot; year &quot;-&quot; month &quot;-&quot; substr($4, 1, 2) &quot; &quot;substr($4, 13, 8) &quot;\&quot;, &quot; year month &quot;);&quot;; }<br />
'</span> <span class="sy0">|</span> <span class="re1">$MYSQL</span> -u<span class="re1">$MYSQL_USER</span> -p<span class="re1">$MYSQL_PASS</span> -D<span class="re1">$MYSQL_DB</span>
        </div>
    </div>
</div>

<p>Удалось обойтись тремя лишними процессами: <span class="codebox"><code class="bash">mysql</code></span>, <span class="codebox"><code class="bash"><span class="kw2">awk</span></code></span> и <span class="codebox"><code class="bash"><span class="kw2">tail</span></code></span> (вместо пяти: <span class="codebox"><code class="bash">mysql</code></span>, <span class="codebox"><code class="bash"><span class="kw2">awk</span></code></span>, <span class="codebox"><code class="bash"><span class="kw2">tail</span></code></span>, <span class="codebox"><code class="bash"><span class="kw2">egrep</span></code></span> и <span class="codebox"><code class="bash"><span class="kw2">sed</span></code></span>).</p>
<p><strong><a href="http://blog.sjinks.pro/mysql/502-counting-traffic-for-nginx-part-2/">Подсчёт трафика в nginx: часть 2</a>.</strong></p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/488-counting-traffic-for-nginx/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Мысли на тему массового UPDATE в MySQL</title>
		<link>http://blog.sjinks.pro/mysql/487-on-bulk-update-in-mysql/</link>
		<comments>http://blog.sjinks.pro/mysql/487-on-bulk-update-in-mysql/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 08:24:16 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[советы]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=487</guid>
		<description><![CDATA[Оказывается, это возможно! INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9) ON DUPLICATE KEY UPDATE `b`=VALUES(`b`), `c`=VALUES(`c`); Например, для WordPress (при условии, что пара (user_id, meta_key) является уникальным ключом): INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES (1, &#039;key1&#039;, &#039;value1&#039;), (1, &#039;key2&#039;, &#039;value2&#039;), (1, &#039;key3&#039;, &#039;value3&#039;), (1, &#039;key4&#039;, [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/487-on-bulk-update-in-mysql/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Оказывается, это возможно!</em></h2>
          
<div class="codebox">
    <div class="the_code" style="" id="p48731">
        <div class="code mysql" id="p487code31">
<span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`table`</span> <span class="br0">&#40;</span><span class="st0">`a`</span><span class="sy2">,</span> <span class="st0">`b`</span><span class="sy2">,</span> <span class="st0">`c`</span><span class="br0">&#41;</span> <span class="kw1">VALUES</span><br />
<span class="br0">&#40;</span>1<span class="sy2">,</span> 2<span class="sy2">,</span> 3<span class="br0">&#41;</span><span class="sy2">,</span> <span class="br0">&#40;</span>4<span class="sy2">,</span> 5<span class="sy2">,</span> 6<span class="br0">&#41;</span><span class="sy2">,</span> <span class="br0">&#40;</span>7<span class="sy2">,</span> 8<span class="sy2">,</span> 9<span class="br0">&#41;</span><br />
<span class="kw1">ON</span> <span class="kw1">DUPLICATE KEY</span> <span class="kw1">UPDATE</span> <span class="st0">`b`</span><span class="sy1">=</span><span class="kw1">VALUES</span><span class="br0">&#40;</span><span class="st0">`b`</span><span class="br0">&#41;</span><span class="sy2">,</span> <span class="st0">`c`</span><span class="sy1">=</span><span class="kw1">VALUES</span><span class="br0">&#40;</span><span class="st0">`c`</span><span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>Например, для <a href="http://blog.sjinks.pro/tag/wordpress/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  WordPress">WordPress</a> (при условии, что пара <code>(user_id, meta_key)</code> является уникальным ключом):</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p48732">
        <div class="code mysql" id="p487code32">
<span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`wp<span class="es1">_</span>usermeta`</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`meta<span class="es1">_</span>key`</span><span class="sy2">,</span> <span class="st0">`meta<span class="es1">_</span>value`</span><span class="br0">&#41;</span> <span class="kw1">VALUES</span><br />
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'key1'</span><span class="sy2">,</span> <span class="st0">'value1'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'key2'</span><span class="sy2">,</span> <span class="st0">'value2'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'key3'</span><span class="sy2">,</span> <span class="st0">'value3'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'key4'</span><span class="sy2">,</span> <span class="st0">'value4'</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'key5'</span><span class="sy2">,</span> <span class="st0">'value5'</span><span class="br0">&#41;</span><br />
<span class="kw1">ON</span> <span class="kw1">DUPLICATE KEY</span> <span class="kw1">UPDATE</span> <span class="st0">`meta<span class="es1">_</span>value`</span><span class="sy1">=</span><span class="kw1">VALUES</span><span class="br0">&#40;</span><span class="st0">`meta<span class="es1">_</span>value`</span><span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p><a href="http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html">Должно работать</a>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/487-on-bulk-update-in-mysql/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/487-on-bulk-update-in-mysql/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Можно ли написать серьёзное web-приложение с использованием MySQL, но без знания принципов работы MySQL?</title>
		<link>http://blog.sjinks.pro/mysql/381-study-mysql/</link>
		<comments>http://blog.sjinks.pro/mysql/381-study-mysql/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 18:48:42 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Патчи]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[ошибка]]></category>
		<category><![CDATA[патч]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=381</guid>
		<description><![CDATA[Можно. Доказано разработчиками WordPress. Хотя я люблю WordPress, но то, что я увидел сегодня в коде, меня сильно потрясло. Речь пойдёт о виджетах, а именно, о календаре и архиве. Я вкратце опишу реализацию каждого из них, а затем расскажу, почему так делать нельзя. Начнём с виджета архивов. В самом простом случае (если не установлено никаких [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/381-study-mysql/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Можно. Доказано разработчиками <a href="http://blog.sjinks.pro/tag/wordpress/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  WordPress">WordPress</a>.</em></h2>
<p>Хотя я люблю WordPress, но то, что я увидел сегодня в коде, меня сильно потрясло.</p>
<p>Речь пойдёт о виджетах, а именно, о календаре и архиве. Я вкратце опишу реализацию каждого из них, а затем расскажу, почему так делать нельзя.<span id="more-381"></span></p>
<p>Начнём с виджета архивов.</p>
<p>В самом простом случае (если не установлено никаких сторонних плагинов, которые могут повлиять на запросы виджета), получение данных для формирования архива производится таким вот запросом (в зависимости от опций виджета запрос может отличаться):</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38154">
        <div class="code mysql" id="p381code54">
<span class="kw1">SELECT</span> <span class="kw1">DISTINCT</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="st0">`year`</span><span class="sy2">,</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="st0">`month`</span><span class="sy2">,</span> <span class="kw22">count</span><span class="br0">&#40;</span>ID<span class="br0">&#41;</span> <span class="kw1">as</span> posts <br />
<span class="kw1">FROM</span> wp_posts <br />
<span class="kw1">WHERE</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span> <br />
<span class="kw1">GROUP BY</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><span class="sy2">,</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><br />
<span class="kw1">ORDER BY</span> post_date <span class="kw1">DESC</span>
        </div>
    </div>
</div>

<p>В случае, если в базе данных хранится несколько тысяч статей и все они опубликованы, фильтрация по полям <code>post_type</code> и <code>post_status</code> мало что даст (если только записи не содержат много вложений), так как всё равно будут выбраны почти все записи. Затем выбранные записи будут группироваться по выражению, и конечный результат будет отсортирован. Проблема здесь состоит в том, что <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> может использовать только один индекс, и он его использует&nbsp;&mdash;&nbsp;для нахождения опубликованных статей. А вот для группировки и сортировки индексы <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> использовать не сможет: в случае с группировкой из-за того, что используется группировка по выражению, а в случае с сортировкой&nbsp;&mdash;&nbsp;потому что группировка и сортировка осуществляются по разным полям.</p>
<p>Запустив EXPLAIN, мы увидим, как всё плохо:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38155">
        <div class="code output" id="p381code55">
+----+-------------+----------+------+------------------+------------------+---------+-------------+------+-----------------------------------------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type | possible_keys &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp; &nbsp; &nbsp; &nbsp; | rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+------+------------------+------------------+---------+-------------+------+-----------------------------------------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | ref &nbsp;| type_status_date | type_status_date | 124 &nbsp; &nbsp; | const,const | 3594 | Using where; Using index; Using temporary; Using filesort | <br />
+----+-------------+----------+------+------------------+------------------+---------+-------------+------+-----------------------------------------------------------+
        </div>
    </div>
</div>

<p>Во-первых, длина ключа не радует: 124 байта&nbsp;&mdash;&nbsp;это перебор. Сравнение длинных строк неэффективно, и чем больше похожих или одинаковых строк, тем хуже <a href="http://blog.sjinks.pro/tag/performance/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  производительность">производительность</a>.</p>
<p>Во-вторых, использование временной таблицы. Создание временной таблицы (пусть даже в памяти)&nbsp;&mdash;&nbsp;это лишнее время. Если таблица становится слишком большой, она сбрасывается на диск и преобразовывается в другой формат. Еще больше потерянного времени.</p>
<p>В-третьих, использование файловой сортировки. MySQL не смог использовать индекс для сортировки; как следствие, ему придётся сделать еще один проход с просмотром всех записей. Опять теряется драгоценное время.</p>
<p>Можно, конечно, поспорить, что современное железо очень быстрое, а память дешёвая. Да, всё так. Но есть одно но: такое решение очень плохо масштабируется. Как следствие, изобретаются различные костыли в виде кэширования. Но не проще ли было нормально спроектировать базу данных?</p>
<p>Как ни крути, запрос переписать невозможно: с ростом количества опубликованных статей производительность будет падать. Что-то мне подсказывает, что нелинейно. А с увеличением количества посетителей производительность будет падать еще сильнее. В результате может упасть MySQL. Или его убьёт знаменитый OOM Killer.</p>
<p>Что нужно было сделать: ввести избыточность в базу данных. С точки зрения третьей нормальной формы это звучит кощунственно. Но избыточность позволяет повысить производительность.</p>
<p>Я внёс изменения в таблицу <code>wp_posts</code>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38156">
        <div class="code mysql" id="p381code56">
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> <span class="st0">`wp<span class="es1">_</span>posts`</span> <span class="kw1">ADD</span> <span class="br0">&#40;</span><span class="st0">`ym`</span> <span class="kw4">MEDIUMINT</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw2">DEFAULT</span> 0<span class="br0">&#41;</span><span class="sy2">;</span><br />
<span class="kw1">UPDATE</span> <span class="st0">`wp<span class="es1">_</span>posts`</span> <span class="kw1">SET</span> <span class="st0">`ym`</span> <span class="sy1">=</span> <span class="kw17">EXTRACT</span><span class="br0">&#40;</span><span class="kw8">YEAR_MONTH</span> <span class="kw1">FROM</span> <span class="st0">`post<span class="es1">_</span>date`</span><span class="br0">&#41;</span><span class="sy2">;</span><br />
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> <span class="st0">`wp<span class="es1">_</span>posts`</span> <span class="kw1">ADD</span> <span class="kw1">KEY</span><span class="br0">&#40;</span><span class="st0">`post<span class="es1">_</span>type`</span><span class="sy2">,</span> <span class="st0">`post<span class="es1">_</span>status`</span><span class="sy2">,</span> <span class="st0">`ym`</span><span class="br0">&#41;</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>Затем переписал запрос:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38157">
        <div class="code mysql" id="p381code57">
<span class="kw1">SELECT</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="st0">`year`</span><span class="sy2">,</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="st0">`month`</span><span class="sy2">,</span> <span class="kw22">count</span><span class="br0">&#40;</span>ID<span class="br0">&#41;</span> <span class="kw1">as</span> posts <br />
<span class="kw1">FROM</span> wp_posts <br />
<span class="kw1">WHERE</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span> <br />
<span class="kw1">GROUP BY</span> <span class="st0">`ym`</span><br />
<span class="kw1">ORDER BY</span> <span class="st0">`ym`</span> <span class="kw1">DESC</span>
        </div>
    </div>
</div>

<p><span class="codebox"><code class="mysql"><span class="kw1">DISTINCT</span></code></span> в запросе явно лишний, потому что группировка по году и месяцу гарантирует, что каждая пара <code>(год, месяц)</code> в результирующем наборе будет уникальной. Сортировка по полной дате также бессмысленна, ибо точность до дня в запросе не нужна.</p>
<p>В результате получаем:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38158">
        <div class="code output" id="p381code58">
+----+-------------+----------+------+----------------------------+-----------+---------+-------------+------+-------------+<br />
| id | select_type | table &nbsp; &nbsp;| type | possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; | key_len | ref &nbsp; &nbsp; &nbsp; &nbsp; | rows | Extra &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+------+----------------------------+-----------+---------+-------------+------+-------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | ref &nbsp;| type_status_date,post_type | post_type | 124 &nbsp; &nbsp; | const,const | 3594 | Using where | <br />
+----+-------------+----------+------+----------------------------+-----------+---------+-------------+------+-------------+
        </div>
    </div>
</div>

<p>Никаких временных таблиц, никакой файловой сортировки. Ключ по-прежнему длинный, но это уже издержки производства. Лично я бы поменял <span class="codebox"><code class="mysql"><span class="kw4">VARCHAR</span></code></span> на <span class="codebox"><code class="mysql"><span class="kw4">ENUM</span></code></span>.</p>
<p>Теперь переходим к виджету календарь.</p>
<p>В нём четыре запроса, но каких!</p>
<ol>
<li>Поиск самой недавней записи прошлых месяцев:
          
<div class="codebox">
    <div class="the_code" style="" id="p38159">
        <div class="code mysql" id="p381code59">
<span class="kw1">SELECT</span> <span class="kw1">DISTINCT</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">month</span><span class="sy2">,</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">year</span><br />
<span class="kw1">FROM</span> wp_posts<br />
<span class="kw1">WHERE</span> post_date <span class="sy1">&lt;</span> <span class="st0">'2008-11-01'</span><br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span><br />
<span class="kw1">ORDER BY</span> post_date <span class="kw1">DESC</span><br />
<span class="kw1">LIMIT</span> <span class="nu0">1</span>
        </div>
    </div>
</div>

<p>Ну зачем нужен <span class="codebox"><code class="mysql"><span class="kw1">DISTINCT</span></code></span>?!! Выбирается <em>одна</em> запись, в результирующем наборе она уникальна в любом случае.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38160">
        <div class="code output" id="p381code60">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | 3238 | Using where; Using index; Using temporary | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+
        </div>
    </div>
</div>

<p>Уберём <span class="codebox"><code class="mysql"><span class="kw1">DISTINCT</span></code></span> и получим более красивый результат:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38161">
        <div class="code output" id="p381code61">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | 3238 | Using where; Using index | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+
        </div>
    </div>
</div>

<p>Как видим, необходимость во временной таблице исчезла.</p>
</li>
<li>Поиск записи в последующих месяцах:
          
<div class="codebox">
    <div class="the_code" style="" id="p38162">
        <div class="code mysql" id="p381code62">
<span class="kw1">SELECT</span> <span class="kw1">DISTINCT</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">month</span><span class="sy2">,</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">year</span><br />
<span class="kw1">FROM</span> wp_posts<br />
<span class="kw1">WHERE</span> post_date <span class="sy1">&gt;</span> <span class="st0">'2008-11-01'</span><br />
<span class="kw10">AND</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span> post_date <span class="br0">&#41;</span> <span class="sy1">!=</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span> <span class="st0">'2008-11-01'</span> <span class="br0">&#41;</span><br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span><br />
<span class="kw1">ORDER BY</span> post_date <span class="kw1">ASC</span><br />
<span class="kw1">LIMIT</span> <span class="nu0">1</span>
        </div>
    </div>
</div>

<p>У нас это называют "начемоданечерезкитайскими методами". Про <span class="codebox"><code class="mysql"><span class="kw1">DISTINCT</span></code></span> я уже говорил, в нём смысла нет. А с датой перемудрили: ищем статьи, написанные после первого числа этого месяца, но не в этом месяце. Не проще ли написать, что ищем статьи, написанные с первого числа следующего месяца?</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38163">
        <div class="code output" id="p381code63">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | &nbsp;356 | Using where; Using index; Using temporary | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+
        </div>
    </div>
</div>

<p>Исправим запрос:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38164">
        <div class="code mysql" id="p381code64">
<span class="kw1">SELECT</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">month</span><span class="sy2">,</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">AS</span> <span class="kw9">year</span><br />
<span class="kw1">FROM</span> wp_posts<br />
<span class="kw1">WHERE</span> post_date <span class="sy1">&gt;</span> <span class="st0">'2008-11-31 23:59:59'</span><br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span><br />
<span class="kw1">ORDER BY</span> post_date <span class="kw1">ASC</span><br />
<span class="kw1">LIMIT</span> <span class="nu0">1</span>
        </div>
    </div>
</div>

          
<div class="codebox">
    <div class="the_code" style="" id="p38165">
        <div class="code output" id="p381code65">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | &nbsp; &nbsp;1 | Using where; Using index |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+--------------------------+
        </div>
    </div>
</div>

</li>
<li>Поиск дней в текущем месяце, в которые была написана хотя бы одна статья:
          
<div class="codebox">
    <div class="the_code" style="" id="p38166">
        <div class="code mysql" id="p381code66">
<span class="kw1">SELECT</span> <span class="kw1">DISTINCT</span> <span class="kw17">DAYOFMONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><br />
<span class="kw1">FROM</span> wp_posts <span class="kw1">WHERE</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="sy1">=</span> <span class="st0">'11'</span><br />
<span class="kw10">AND</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="sy1">=</span> <span class="st0">'2008'</span><br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span><br />
<span class="kw10">AND</span> post_date <span class="sy1">&lt;</span> <span class="st0">'2008-11-24 18:30:04'</span>
        </div>
    </div>
</div>

<p>Очевидно, что MySQL сможет использовать только стратегию range. В случае, если рассматриваемый месяц является последним в базе данных, MySQL придётся просмотреть все записи, которые вернёт <span class="codebox"><code class="mysql"><span class="kw1">WHERE</span></code></span>. Ибо не умеет MySQL использовать индексы с выражениями.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38167">
        <div class="code output" id="p381code67">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | 3594 | Using where; Using index; Using temporary | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+
        </div>
    </div>
</div>

<p>MySQL придётся просмотреть 3594 записи. А если мы перепишем запрос:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38168">
        <div class="code mysql" id="p381code68">
<span class="kw1">SELECT</span> <span class="kw1">DISTINCT</span> <span class="kw17">DAYOFMONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><br />
<span class="kw1">FROM</span> wp_posts<br />
<span class="kw1">WHERE</span> post_date <span class="sy1">&gt;=</span> <span class="st0">'2008-11-01 00:00:00'</span><br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span><br />
<span class="kw10">AND</span> post_date <span class="sy1">&lt;</span> <span class="st0">'2008-11-24 18:30:04'</span>
        </div>
    </div>
</div>

          
<div class="codebox">
    <div class="the_code" style="" id="p38169">
        <div class="code output" id="p381code69">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | &nbsp;267 | Using where; Using index; Using temporary | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------------------------------------+
        </div>
    </div>
</div>

<p>Получим более, чем 10-кратную экономию. Ain't it sweet?</p>
</li>
<li>Получение дней и соответствующих им статей:
          
<div class="codebox">
    <div class="the_code" style="" id="p38170">
        <div class="code mysql" id="p381code70">
<span class="kw1">SELECT</span> post_title<span class="sy2">,</span> <span class="kw17">DAYOFMONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="kw1">as</span> dom <br />
<span class="kw1">FROM</span> wp_posts <br />
<span class="kw1">WHERE</span> <span class="kw18">YEAR</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="sy1">=</span> <span class="st0">'2008'</span> <br />
<span class="kw10">AND</span> <span class="kw18">MONTH</span><span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <span class="sy1">=</span> <span class="st0">'11'</span> <br />
<span class="kw10">AND</span> post_date <span class="sy1">&lt;</span> <span class="st0">'2008-11-24 18:30:04'</span> <br />
<span class="kw10">AND</span> post_type <span class="sy1">=</span> <span class="st0">'post'</span> <br />
<span class="kw10">AND</span> post_status <span class="sy1">=</span> <span class="st0">'publish'</span>
        </div>
    </div>
</div>

<p>Та же самая <a href="http://blog.sjinks.pro/tag/bug/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  ошибка">ошибка</a>, что и в прошлый раз.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38171">
        <div class="code output" id="p381code71">
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------+<br />
| id | select_type | table &nbsp; &nbsp;| type &nbsp;| possible_keys &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| wp_posts | range | type_status_date,post_type | type_status_date | 132 &nbsp; &nbsp; | NULL | 3594 | Using where | <br />
+----+-------------+----------+-------+----------------------------+------------------+---------+------+------+-------------+
        </div>
    </div>
</div>

Запрос переписывается аналогично. Переписали всего два запроса и получили ощутимый прирост в производительности.
</li>
</ol>
<p>Теперь, собственно, патчи.</p>
<ul>
<li><strong><a href="http://blog.sjinks.pro/tag/patch/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  патч">Патч</a> для WordPress 2.6.x:</strong>
          
<div class="codebox">
    <div class="the_code" style="" id="p38172">
        <div class="code diff" id="p381code72">
--- general-template.php.original &nbsp; &nbsp; &nbsp; 2008-06-11 20:25:55.000000000 +0300<br />
<span class="re4">+++ general-template.php &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2008</span>-<span class="nu0">11</span>-<span class="nu0">24</span> <span class="nu0">20</span>:<span class="nu0">37</span>:<span class="nu0">42.000000000</span> +0200</span><br />
<span class="re6">@@ -<span class="nu0">414</span>,<span class="nu0">7</span> +<span class="nu0">414</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $join = apply_filters<span class="br0">&#40;</span>'getarchives_join', &quot;&quot;, $r<span class="br0">&#41;</span>;<br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> 'monthly' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">435</span>,<span class="nu0">7</span> +<span class="nu0">435</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span>'yearly' == $type<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">456</span>,<span class="nu0">7</span> +<span class="nu0">456</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span> 'daily' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">557</span>,<span class="nu0">7</span> +<span class="nu0">557</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ob_start<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Quick check. If we have no posts at all, abort!<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$posts <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1&quot;<span class="br0">&#41;</span>;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1&quot;<span class="br0">&#41;</span>;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$gotsome <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="re6">@@ -<span class="nu0">591</span>,<span class="nu0">16</span> +<span class="nu0">591</span>,<span class="nu0">16</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $unixmonth = mktime<span class="br0">&#40;</span>0, 0 , 0, $thismonth, 1, $thisyear<span class="br0">&#41;</span>;<br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get the next and previous month and year with at least one post<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &lt; '$thisyear-$thismonth-01'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER BY post_date DESC<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>;<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT &nbsp;DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $last_day = date<span class="br0">&#40;</span>'t'<span class="br0">&#41;</span>;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; &nbsp; &nbsp; &nbsp; '$thisyear-$thismonth-01'</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND MONTH<span class="br0">&#40;</span> post_date <span class="br0">&#41;</span> != MONTH<span class="br0">&#40;</span> '$thisyear-$thismonth-01' <span class="br0">&#41;</span></span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; '$thisyear-$thismonth-<span class="br0">&#123;</span>$last_day<span class="br0">&#125;</span> <span class="nu0">23</span>:<span class="nu0">59</span>:<span class="nu0">59</span>'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER &nbsp; BY post_date ASC<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>;<br />
<span class="re6">@@ -<span class="nu0">655</span>,<span class="nu0">8</span> +<span class="nu0">655</span>,<span class="nu0">7</span> @@</span><br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get days with posts<br />
&nbsp; &nbsp; &nbsp; &nbsp; $dayswithposts = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT DISTINCT DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth'</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear'</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_date &lt; '&quot; . current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span> . '\'', ARRAY_N<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> $dayswithposts <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">675</span>,<span class="nu0">8</span> +<span class="nu0">674</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_titles_for_day = array<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_post_titles = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT post_title, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> as dom &quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;FROM $wpdb-&gt;posts &quot;<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear' &quot;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth' &quot;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00' &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_date &lt; '&quot;.current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span>.&quot;' &quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_type = 'post' AND post_status = 'publish'&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;
        </div>
    </div>
</div>

</li>
<li><strong>Патч для WordPress 2.7b3:</strong>
          
<div class="codebox">
    <div class="the_code" style="" id="p38173">
        <div class="code diff" id="p381code73">
--- general-template.php.original &nbsp; &nbsp; &nbsp; 2008-11-13 09:45:11.000000000 +0200 <br />
<span class="re4">+++ general-template.php &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2008</span>-<span class="nu0">11</span>-<span class="nu0">24</span> <span class="nu0">20</span>:<span class="nu0">45</span>:<span class="nu0">36.000000000</span> +0200 </span><br />
<span class="re6">@@ -<span class="nu0">750</span>,<span class="nu0">7</span> +<span class="nu0">750</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $output = ''; <br />
&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> 'monthly' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_da</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re6">@@ -<span class="nu0">771</span>,<span class="nu0">7</span> +<span class="nu0">771</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span>'yearly' == $type<span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;; </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;; </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re6">@@ -<span class="nu0">792</span>,<span class="nu0">7</span> +<span class="nu0">792</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span> 'daily' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_d</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MON</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re6">@@ -<span class="nu0">913</span>,<span class="nu0">7</span> +<span class="nu0">913</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ob_start<span class="br0">&#40;</span><span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; // Quick check. If we have no posts at all, abort! <br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$posts <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1&quot;<span class="br0">&#41;</span>; </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1&quot;<span class="br0">&#41;</span>; </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$gotsome <span class="br0">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <br />
<span class="re6">@@ -<span class="nu0">947</span>,<span class="nu0">16</span> +<span class="nu0">947</span>,<span class="nu0">16</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $unixmonth = mktime<span class="br0">&#40;</span>0, 0 , 0, $thismonth, 1, $thisyear<span class="br0">&#41;</span>; <br />
&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get the next and previous month and year with at least one post <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &lt; '$thisyear-$thismonth-01' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER BY post_date DESC <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>; <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT &nbsp;DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $last_day = date<span class="br0">&#40;</span>'t'<span class="br0">&#41;</span>; </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; &nbsp; &nbsp; &nbsp; '$thisyear-$thismonth-01' </span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND MONTH<span class="br0">&#40;</span> post_date <span class="br0">&#41;</span> != MONTH<span class="br0">&#40;</span> '$thisyear-$thismonth-01' <span class="br0">&#41;</span> </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; &nbsp; &nbsp; &nbsp; '$thisyear-$thismonth-<span class="br0">&#123;</span>$last_day<span class="br0">&#125;</span> <span class="nu0">23</span>:<span class="nu0">59</span>:<span class="nu0">59</span>' </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER &nbsp; BY post_date ASC <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>; <br />
<span class="re6">@@ -<span class="nu0">1011</span>,<span class="nu0">8</span> +<span class="nu0">1011</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get days with posts <br />
&nbsp; &nbsp; &nbsp; &nbsp; $dayswithposts = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT DISTINCT DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth' </span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear' </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00' </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_date &lt; '&quot; . current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span> . '\'', ARRAY_N<span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> $dayswithposts <span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="re6">@@ -<span class="nu0">1031</span>,<span class="nu0">8</span> +<span class="nu0">1030</span>,<span class="nu0">7</span> @@ </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_titles_for_day = array<span class="br0">&#40;</span><span class="br0">&#41;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_post_titles = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT post_title, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> as dom &quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;FROM $wpdb-&gt;posts &quot; <br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear' &quot; </span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth' &quot; </span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00' &quot; </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_date &lt; '&quot;.current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span>.&quot;' &quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_type = 'post' AND post_status = 'publish'&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;
        </div>
    </div>
</div>

</li>
</ul>
<p>Патч нужно применять к файлу <code>wp-includes/general-template.<a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">php</a></code>.</p>
<p><strong>Патч для версии 2.7.1 (также решает проблему с <a href="http://core.trac.wordpress.org/ticket/9197">#9197</a>):</strong></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p38174">
        <div class="code diff" id="p381code74">
Index: general-template.php<br />
===================================================================<br />
<span class="re3">--- general-template.php &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span>revision <span class="nu0">10674</span><span class="br0">&#41;</span></span><br />
<span class="re4">+++ general-template.php &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span>working copy<span class="br0">&#41;</span></span><br />
<span class="re6">@@ -<span class="nu0">750</span>,<span class="nu0">7</span> +<span class="nu0">750</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $output = '';<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> 'monthly' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">771</span>,<span class="nu0">7</span> +<span class="nu0">771</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span>'yearly' == $type<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">792</span>,<span class="nu0">7</span> +<span class="nu0">792</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> elseif <span class="br0">&#40;</span> 'daily' == $type <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT DISTINCT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = &quot;SELECT YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `year`, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `month`, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS `dayofmonth`, count<span class="br0">&#40;</span>ID<span class="br0">&#41;</span> as posts FROM $wpdb-&gt;posts $join $where GROUP BY YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span>, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> ORDER BY post_date DESC $limit&quot;;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key = md5<span class="br0">&#40;</span>$query<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $cache = wp_cache_get<span class="br0">&#40;</span> 'wp_get_archives' , 'general'<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !isset<span class="br0">&#40;</span> $cache<span class="br0">&#91;</span> $key <span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re6">@@ -<span class="nu0">913</span>,<span class="nu0">7</span> +<span class="nu0">913</span>,<span class="nu0">7</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ob_start<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Quick check. If we have no posts at all, abort!<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$posts <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1&quot;<span class="br0">&#41;</span>;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $gotsome = $wpdb-&gt;get_var<span class="br0">&#40;</span>&quot;SELECT ID from $wpdb-&gt;posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1&quot;<span class="br0">&#41;</span>;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> !$gotsome <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="re6">@@ -<span class="nu0">947</span>,<span class="nu0">16</span> +<span class="nu0">947</span>,<span class="nu0">16</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $unixmonth = mktime<span class="br0">&#40;</span>0, 0 , 0, $thismonth, 1, $thisyear<span class="br0">&#41;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get the next and previous month and year with at least one post<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $previous = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &lt; '$thisyear-$thismonth-01'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER BY post_date DESC<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>;<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT &nbsp;DISTINCT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $last_day = date<span class="br0">&#40;</span>'t', $unixmonth<span class="br0">&#41;</span>;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; $next = $wpdb-&gt;get_row<span class="br0">&#40;</span>&quot;SELECT MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS month, YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> AS year</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; &nbsp; &nbsp; &nbsp; '$thisyear-$thismonth-01'</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND MONTH<span class="br0">&#40;</span> post_date <span class="br0">&#41;</span> != MONTH<span class="br0">&#40;</span> '$thisyear-$thismonth-01' <span class="br0">&#41;</span></span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE post_date &gt; '$thisyear-$thismonth-<span class="br0">&#123;</span>$last_day<span class="br0">&#125;</span> <span class="nu0">23</span>:<span class="nu0">59</span>:<span class="nu0">59</span>'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER &nbsp; BY post_date ASC<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LIMIT 1&quot;<span class="br0">&#41;</span>;<br />
<span class="re6">@@ -<span class="nu0">1011</span>,<span class="nu0">10</span> +<span class="nu0">1011</span>,<span class="nu0">9</span> @@</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; // Get days with posts<br />
&nbsp; &nbsp; &nbsp; &nbsp; $dayswithposts = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT DISTINCT DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth'</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear'</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM $wpdb-&gt;posts WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_type = 'post' AND post_status = 'publish'<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_date &lt; '&quot; . current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span> . '\'', ARRAY_N<span class="br0">&#41;</span>;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND post_date &lt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$last_day<span class="br0">&#125;</span> 23:59:59'&quot;, ARRAY_N<span class="br0">&#41;</span>;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> $dayswithposts <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach <span class="br0">&#40;</span> <span class="br0">&#40;</span>array<span class="br0">&#41;</span> $dayswithposts as $daywith <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $daywithpost<span class="br0">&#91;</span><span class="br0">&#93;</span> = $daywith<span class="br0">&#91;</span>0<span class="br0">&#93;</span>;<br />
<span class="re6">@@ -<span class="nu0">1031</span>,<span class="nu0">9</span> +<span class="nu0">1030</span>,<span class="nu0">8</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_titles_for_day = array<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $ak_post_titles = $wpdb-&gt;get_results<span class="br0">&#40;</span>&quot;SELECT post_title, DAYOFMONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> as dom &quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;FROM $wpdb-&gt;posts &quot;<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE YEAR<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thisyear' &quot;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND MONTH<span class="br0">&#40;</span>post_date<span class="br0">&#41;</span> = '$thismonth' &quot;</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_date &lt; '&quot;.current_time<span class="br0">&#40;</span>'mysql'<span class="br0">&#41;</span>.&quot;' &quot;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;WHERE post_date &gt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-01 00:00:00' &quot;</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_date &lt;= '<span class="br0">&#123;</span>$thisyear<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$thismonth<span class="br0">&#125;</span>-<span class="br0">&#123;</span>$last_day<span class="br0">&#125;</span> <span class="nu0">23</span>:<span class="nu0">59</span>:<span class="nu0">59</span>' &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .&quot;AND post_type = 'post' AND post_status = 'publish'&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; if <span class="br0">&#40;</span> $ak_post_titles <span class="br0">&#41;</span> <span class="br0">&#123;</span>
        </div>
    </div>
</div>

<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/381-study-mysql/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/381-study-mysql/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Чудеса&#8230;</title>
		<link>http://blog.sjinks.pro/mysql/327-shit-happens/</link>
		<comments>http://blog.sjinks.pro/mysql/327-shit-happens/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 03:42:52 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Юмор]]></category>
		<category><![CDATA[ошибка]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=327</guid>
		<description><![CDATA[Если MySQL не находит строку, значит, он её плохо ищет Началось всё с того, что я забыл заплатить за Internet, и в благодарность за это мой провайдер меня безжалостно отрубил. Дело было вечером, делать было нечего, тем более, что я давно собирался написать статью про MySQL. И вот, когда я стал генерировать тестовую таблицу, начались [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/327-shit-happens/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Если <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> не находит строку, значит, он её плохо ищет</em></h2>
<p>Началось всё с того, что я забыл заплатить за Internet, и в благодарность за это мой провайдер меня безжалостно отрубил. Дело было вечером, делать было нечего, тем более, что я давно собирался написать статью про MySQL. И вот, когда я стал генерировать тестовую таблицу, начались чудеса&hellip;<span id="more-327"></span></p>
<p>Создал в MySQL таблицу:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32785">
        <div class="code mysql" id="p327code85">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test`</span> <span class="br0">&#40;</span><br />
&nbsp; <span class="st0">`id`</span> <span class="kw4">bigint</span><span class="br0">&#40;</span>20<span class="br0">&#41;</span> <span class="kw6">unsigned</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">auto_increment</span><span class="sy2">,</span><br />
&nbsp; <span class="st0">`k`</span> <span class="kw4">int</span><span class="br0">&#40;</span>10<span class="br0">&#41;</span> <span class="kw6">unsigned</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; <span class="st0">`data`</span> <span class="kw4">varchar</span><span class="br0">&#40;</span>40<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">PRIMARY KEY</span> &nbsp;<span class="br0">&#40;</span><span class="st0">`id`</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">KEY</span> <span class="st0">`k<span class="es1">_</span>2`</span> <span class="br0">&#40;</span><span class="st0">`k`</span><span class="sy2">,</span><span class="st0">`id`</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">KEY</span> <span class="st0">`k`</span> <span class="br0">&#40;</span><span class="st0">`k`</span><span class="sy2">,</span><span class="st0">`data`</span><span class="br0">&#41;</span><br />
<span class="br0">&#41;</span> <span class="kw1">ENGINE</span><span class="sy1">=</span>MyISAM <span class="kw2">DEFAULT</span> <span class="kw7">CHARSET</span><span class="sy1">=</span>latin1
        </div>
    </div>
</div>

<p><a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">PHP</a>-скриптом запихнул в неё данные:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32786">
        <div class="code php" id="p327code86">
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span><span class="sy0">=</span><span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">&lt;</span><span class="nu0">1000000</span><span class="sy0">;</span> <span class="sy0">++</span><span class="re0">$i</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$key</span> &nbsp;<span class="sy0">=</span> <span class="re0">$i</span> <span class="sy0">%</span> <span class="nu0">1000</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> <span class="sy0">=</span> <span class="kw3">sha1</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;INSERT DELAYED INTO `test` VALUES (NULL, <span class="es4">{$key}</span>, '<span class="es4">{$data}</span>')&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Сделал два <span class="codebox"><code class="mysql"><span class="kw2">INSERT</span></code></span>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32787">
        <div class="code mysql" id="p327code87">
<span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`test`</span> <span class="kw1">SELECT</span> <span class="kw3">NULL</span><span class="sy2">,</span> <span class="st0">`k`</span><span class="sy2">,</span> <span class="st0">`data`</span> <span class="kw1">FROM</span> <span class="st0">`test`</span><span class="sy2">;</span><br />
<span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`test`</span> <span class="kw1">SELECT</span> <span class="kw3">NULL</span><span class="sy2">,</span> <span class="st0">`k`</span><span class="sy2">,</span> <span class="st0">`data`</span> <span class="kw1">FROM</span> <span class="st0">`test`</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>В результате получил 4,000,000 строк в таблице.</p>
<p>Теперь самое интересное:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32788">
        <div class="code text" id="p327code88">
mysql&gt; SELECT * FROM test WHERE `k` = 5 ORDER BY `data` LIMIT 5;<br />
+------+---+------------------------------------------+<br />
| id &nbsp; | k | data &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+------+---+------------------------------------------+<br />
| &nbsp; &nbsp;6 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 1006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 2006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 3006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 4006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
+------+---+------------------------------------------+<br />
5 rows in set (0.00 sec)<br />
<br />
mysql&gt; SELECT * FROM test WHERE `k` = 5 LIMIT 5;<br />
+------+---+------------------------------------------+<br />
| id &nbsp; | k | data &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+------+---+------------------------------------------+<br />
| &nbsp; &nbsp;6 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 1006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 2006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 3006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 4006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
+------+---+------------------------------------------+<br />
5 rows in set (0.00 sec)<br />
<br />
mysql&gt; SELECT * FROM test WHERE `k` = 5 ORDER BY `data` DESC LIMIT 5;<br />
&lt;strong&gt;Empty set (0.01 sec)&lt;/strong&gt;<br />
<br />
mysql&gt; EXPLAIN SELECT * FROM test WHERE `k` = 5 ORDER BY `data` DESC LIMIT 5;<br />
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+<br />
| id | select_type | table | type | possible_keys | key &nbsp;| key_len | ref &nbsp; | rows | Extra &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| test &nbsp;| ref &nbsp;| k_2,k &nbsp; &nbsp; &nbsp; &nbsp; | k &nbsp; &nbsp;| 4 &nbsp; &nbsp; &nbsp; | const | 3831 | Using where |<br />
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+<br />
1 row in set (0.00 sec)<br />
<br />
mysql&gt; SELECT * FROM test WHERE `k` = 5 LIMIT 5;<br />
+------+---+------------------------------------------+<br />
| id &nbsp; | k | data &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
+------+---+------------------------------------------+<br />
| &nbsp; &nbsp;6 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 1006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 2006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 3006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
| 4006 | 5 | ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 |<br />
+------+---+------------------------------------------+<br />
5 rows in set (0.00 sec)
        </div>
    </div>
</div>

<p>Внимание, вопрос: какого икса MySQL выдает результаты, если сортировка не осуществляется, либо осуществляется по возрастанию, но не выдает результаты, если сортируем по убыванию?</p>
<p>По ходу я нашел неизвестный баг в <a href="http://blog.sjinks.pro/tag/myisam/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MyISAM">MyISAM</a>? <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32789">
        <div class="code mysql" id="p327code89">
mysql<span class="sy1">&gt;</span> <span class="kw1">SHOW</span> <span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test`</span>\G<br />
<span class="sy1">***************************</span> 1. row <span class="sy1">***************************</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">Table</span>: test<br />
<span class="kw1">Create</span> <span class="kw1">Table</span>: <span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test`</span> <span class="br0">&#40;</span><br />
&nbsp; <span class="st0">`id`</span> <span class="kw4">bigint</span><span class="br0">&#40;</span>20<span class="br0">&#41;</span> <span class="kw6">unsigned</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">auto_increment</span><span class="sy2">,</span><br />
&nbsp; <span class="st0">`k`</span> <span class="kw4">int</span><span class="br0">&#40;</span>10<span class="br0">&#41;</span> <span class="kw6">unsigned</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; <span class="st0">`data`</span> <span class="kw4">varchar</span><span class="br0">&#40;</span>40<span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">PRIMARY KEY</span> &nbsp;<span class="br0">&#40;</span><span class="st0">`id`</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">KEY</span> <span class="st0">`k<span class="es1">_</span>2`</span> <span class="br0">&#40;</span><span class="st0">`k`</span><span class="sy2">,</span><span class="st0">`id`</span><span class="br0">&#41;</span><span class="sy2">,</span><br />
&nbsp; <span class="kw1">KEY</span> <span class="st0">`k`</span> <span class="br0">&#40;</span><span class="st0">`k`</span><span class="sy2">,</span><span class="st0">`data`</span><span class="br0">&#41;</span><br />
<span class="br0">&#41;</span> <span class="kw1">ENGINE</span><span class="sy1">=</span>MyISAM <span class="kw6">AUTO_INCREMENT</span><span class="sy1">=</span>4000001 <span class="kw2">DEFAULT</span> <span class="kw7">CHARSET</span><span class="sy1">=</span>latin1<br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SHOW</span> <span class="kw1">TABLE</span> <span class="kw1">STATUS</span><span class="sy2">;</span><br />
<span class="sy1">+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
<span class="sy1">|</span> Name <span class="sy1">|</span> <span class="kw1">Engine</span> <span class="sy1">|</span> <span class="kw23">Version</span> <span class="sy1">|</span> <span class="kw6">Row_format</span> <span class="sy1">|</span> Rows &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw6">Avg_row_length</span> <span class="sy1">|</span> Data_length <span class="sy1">|</span> Max_data_length <span class="sy1">|</span> Index_length <span class="sy1">|</span> Data_free <span class="sy1">|</span> <span class="kw6">Auto_increment</span> <span class="sy1">|</span> Create_time &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> Update_time &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> Check_time &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw23">Collation</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> <span class="kw6">Checksum</span> <span class="sy1">|</span> Create_options <span class="sy1">|</span> <span class="kw1">Comment</span> <span class="sy1">|</span><br />
<span class="sy1">+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
<span class="sy1">|</span> test <span class="sy1">|</span> MyISAM <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;10 <span class="sy1">|</span> Dynamic &nbsp; &nbsp;<span class="sy1">|</span> 4000000 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 59 <span class="sy1">|</span> &nbsp; 239984000 <span class="sy1">|</span> 281474976710655 <span class="sy1">|</span> &nbsp; &nbsp;148987904 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; 0 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp;4000001 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 04:17:14 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 04:21:23 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 04:21:49 <span class="sy1">|</span> latin1_swedish_ci <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<pre>
$ mysql --version
mysql  Ver 14.12 Distrib 5.0.51a, for debian-<a href="http://blog.sjinks.pro/tag/linux/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Linux">linux</a>-gnu (x86_64) using readline 5.2
$ uname -srvmo
<a href="http://blog.sjinks.pro/tag/linux/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Linux">Linux</a> 2.6.24-21-server #1 SMP Mon Aug 25 17:28:54 UTC 2008 x86_64 GNU/<a href="http://blog.sjinks.pro/tag/linux/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Linux">Linux</a>
</pre>
<p>Для очистки совести:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32790">
        <div class="code mysql" id="p327code90">
mysql<span class="sy1">&gt;</span> <span class="kw1">CHECK</span> <span class="kw1">TABLE</span> test <span class="kw1">EXTENDED</span><span class="sy2">;</span><br />
<span class="sy1">+-----------+-------+----------+----------+</span><br />
<span class="sy1">|</span> <span class="kw1">Table</span> &nbsp; &nbsp; <span class="sy1">|</span> Op &nbsp; &nbsp;<span class="sy1">|</span> Msg_type <span class="sy1">|</span> Msg_text <span class="sy1">|</span><br />
<span class="sy1">+-----------+-------+----------+----------+</span><br />
<span class="sy1">|</span> test.test <span class="sy1">|</span> <span class="kw1">check</span> <span class="sy1">|</span> <span class="kw1">status</span> &nbsp; <span class="sy1">|</span> OK &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+-----------+-------+----------+----------+</span><br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>2 <span class="kw22">min</span> 48.13 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">EXPLAIN</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> <span class="st0">`k`</span> <span class="sy1">=</span> 5 <span class="kw1">ORDER BY</span> <span class="st0">`data`</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
<span class="sy1">+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+</span><br />
<span class="sy1">|</span> id <span class="sy1">|</span> select_type <span class="sy1">|</span> <span class="kw1">table</span> <span class="sy1">|</span> <span class="kw1">type</span> <span class="sy1">|</span> possible_keys <span class="sy1">|</span> <span class="kw1">key</span> &nbsp;<span class="sy1">|</span> key_len <span class="sy1">|</span> ref &nbsp; <span class="sy1">|</span> rows <span class="sy1">|</span> Extra &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+</span><br />
<span class="sy1">|</span> &nbsp;1 <span class="sy1">|</span> <span class="kw1">SIMPLE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> ref &nbsp;<span class="sy1">|</span> k_2<span class="sy2">,</span>k &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> k &nbsp; &nbsp;<span class="sy1">|</span> 4 &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> const <span class="sy1">|</span> 3831 <span class="sy1">|</span> <span class="kw1">Using</span> <span class="kw1">where</span> <span class="sy1">|</span><br />
<span class="sy1">+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+</span><br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> <span class="st0">`k`</span> <span class="sy1">=</span> 5 <span class="kw1">ORDER BY</span> <span class="st0">`data`</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
Empty <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SHOW</span> <span class="kw1">KEYS</span> <span class="kw1">FROM</span> test<span class="sy2">;</span><br />
<span class="sy1">+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+</span><br />
<span class="sy1">|</span> <span class="kw1">Table</span> <span class="sy1">|</span> Non_unique <span class="sy1">|</span> Key_name <span class="sy1">|</span> Seq_in_index <span class="sy1">|</span> Column_name <span class="sy1">|</span> <span class="kw23">Collation</span> <span class="sy1">|</span> Cardinality <span class="sy1">|</span> Sub_part <span class="sy1">|</span> Packed <span class="sy1">|</span> <span class="kw3">Null</span> <span class="sy1">|</span> Index_type <span class="sy1">|</span> <span class="kw1">Comment</span> <span class="sy1">|</span><br />
<span class="sy1">+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 <span class="sy1">|</span> PRIMARY &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> A &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; 4000000 <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw1">BTREE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k_2 &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> A &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp;1000 <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw1">BTREE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k_2 &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 <span class="sy1">|</span> id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> A &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; 4000000 <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw1">BTREE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> A &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp;1000 <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw1">BTREE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 <span class="sy1">|</span> k &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 <span class="sy1">|</span> <span class="kw1">data</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> A &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp;1000 <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw1">BTREE</span> &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+</span><br />
5 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">ALTER</span> <span class="kw1">TABLE</span> test <span class="kw1">DROP</span> <span class="kw1">KEY</span> k_2<span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 4000000 rows affected <span class="br0">&#40;</span>35.48 sec<span class="br0">&#41;</span><br />
Records: 4000000 &nbsp;Duplicates: 0 &nbsp;<span class="kw1">Warnings</span>: 0<br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> <span class="st0">`k`</span> <span class="sy1">=</span> 5 <span class="kw1">ORDER BY</span> <span class="st0">`data`</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
Empty <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>Естественно, я перезагрузился, тщательно проверил диски на наличие ошибок, грохнул базу, создал её заново, перезапустил сервер&nbsp;&mdash;&nbsp;<a href="http://blog.sjinks.pro/tag/bug/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  ошибка">ошибка</a> не исчезла. Создал еще парочку баз с теми же данными&nbsp;&mdash;&nbsp;без изменений.</p>
<p>Сделал так:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32791">
        <div class="code mysql" id="p327code91">
mysql<span class="sy1">&gt;</span> <span class="kw1">CREATE</span> <span class="kw1">TABLE</span> test2 <span class="kw1">AS</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test<span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 4000000 rows affected <span class="br0">&#40;</span>4.67 sec<span class="br0">&#41;</span><br />
Records: 4000000 &nbsp;Duplicates: 0 &nbsp;<span class="kw1">Warnings</span>: 0<br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
Empty <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test2 <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> id &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> k <span class="sy1">|</span> <span class="kw1">data</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> 2686006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2669006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2668006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2667006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2666006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
5 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">1.56</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>Минут через пять я вспомнил, что <span class="codebox"><code class="mysql"><span class="kw1">CREATE</span> <span class="kw1">TABLE</span> ... <span class="kw1">SELECT</span></code></span> не создаёт индексы. Я решил проверить догадку:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32792">
        <div class="code mysql" id="p327code92">
mysql<span class="sy1">&gt;</span> <span class="kw1">SHOW</span> <span class="kw1">TABLE</span> <span class="kw1">STATUS</span><span class="sy2">;</span><br />
<span class="sy1">+-------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
<span class="sy1">|</span> Name &nbsp;<span class="sy1">|</span> <span class="kw1">Engine</span> <span class="sy1">|</span> <span class="kw23">Version</span> <span class="sy1">|</span> <span class="kw6">Row_format</span> <span class="sy1">|</span> Rows &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw6">Avg_row_length</span> <span class="sy1">|</span> Data_length <span class="sy1">|</span> Max_data_length <span class="sy1">|</span> Index_length <span class="sy1">|</span> Data_free <span class="sy1">|</span> <span class="kw6">Auto_increment</span> <span class="sy1">|</span> Create_time &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> Update_time &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> Check_time &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> <span class="kw23">Collation</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> <span class="kw6">Checksum</span> <span class="sy1">|</span> Create_options <span class="sy1">|</span> <span class="kw1">Comment</span> <span class="sy1">|</span><br />
<span class="sy1">+-------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
<span class="sy1">|</span> test &nbsp;<span class="sy1">|</span> MyISAM <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;10 <span class="sy1">|</span> Dynamic &nbsp; &nbsp;<span class="sy1">|</span> 4000000 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 59 <span class="sy1">|</span> &nbsp; 239984000 <span class="sy1">|</span> 281474976710655 <span class="sy1">|</span> &nbsp; &nbsp;149490688 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; 0 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp;4000001 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 05:28:36 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 05:29:16 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 05:29:41 <span class="sy1">|</span> latin1_swedish_ci <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">|</span> test2 <span class="sy1">|</span> MyISAM <span class="sy1">|</span> &nbsp; &nbsp; &nbsp;10 <span class="sy1">|</span> Dynamic &nbsp; &nbsp;<span class="sy1">|</span> 4000000 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 59 <span class="sy1">|</span> &nbsp; 239984000 <span class="sy1">|</span> 281474976710655 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; 1024 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; 0 <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 05:35:17 <span class="sy1">|</span> 2008<span class="sy1">-</span>09<span class="sy1">-</span>01 05:35:22 <span class="sy1">|</span> <span class="kw3">NULL</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> latin1_swedish_ci <span class="sy1">|</span> &nbsp; &nbsp; <span class="kw3">NULL</span> <span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+-------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+</span><br />
2 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">ALTER</span> <span class="kw1">TABLE</span> test <span class="kw1">DROP</span> <span class="kw1">KEY</span> k<span class="sy2">,</span> <span class="kw1">DROP</span> <span class="kw1">KEY</span> k_2<span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 4000000 rows affected <span class="br0">&#40;</span>14.11 sec<span class="br0">&#41;</span><br />
Records: 4000000 &nbsp;Duplicates: 0 &nbsp;<span class="kw1">Warnings</span>: 0<br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> id &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> k <span class="sy1">|</span> <span class="kw1">data</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> 2686006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2669006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2668006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2667006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 2666006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
5 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>1.63 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">ALTER</span> <span class="kw1">TABLE</span> test <span class="kw1">ADD</span> <span class="kw1">KEY</span> <span class="br0">&#40;</span>k<span class="sy2">,</span> <span class="kw1">data</span><span class="br0">&#41;</span><span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 4000000 rows affected <span class="br0">&#40;</span>30.35 sec<span class="br0">&#41;</span><br />
Records: 4000000 &nbsp;Duplicates: 0 &nbsp;<span class="kw1">Warnings</span>: 0<br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
Empty <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">ANALYZE</span> <span class="kw1">TABLE</span> test<span class="sy2">;</span><br />
<span class="sy1">+-----------+---------+----------+-----------------------------+</span><br />
<span class="sy1">|</span> <span class="kw1">Table</span> &nbsp; &nbsp; <span class="sy1">|</span> Op &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> Msg_type <span class="sy1">|</span> Msg_text &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">|</span><br />
<span class="sy1">+-----------+---------+----------+-----------------------------+</span><br />
<span class="sy1">|</span> test.test <span class="sy1">|</span> <span class="kw1">analyze</span> <span class="sy1">|</span> <span class="kw1">status</span> &nbsp; <span class="sy1">|</span> <span class="kw1">Table</span> <span class="kw10">is</span> already up <span class="kw1">to</span> <span class="kw5">date</span> <span class="sy1">|</span><br />
<span class="sy1">+-----------+---------+----------+-----------------------------+</span><br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>Вот они, чудеса! Точнее, баги. С индексом MySQL не находит нужные строки, без индекса же всё работает. Причем самое странное то, что не работает только k=5; другие значения срабатывают просто на "ура".</p>
<p>Что характерно: я грохнул 2 миллиона строк (эх!) и оптимизировал таблИцу, и всё заработало:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32793">
        <div class="code mysql" id="p327code93">
mysql<span class="sy1">&gt;</span> <span class="kw1">DELETE</span> <span class="kw1">FROM</span> test <span class="kw1">ORDER BY</span> id <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">2000000</span><span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 2000000 rows affected <span class="br0">&#40;</span>1 <span class="kw22">min</span> 17.53 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
Empty <span class="kw1">set</span> <span class="br0">&#40;</span>0.00 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">OPTIMIZE</span> <span class="kw1">TABLE</span> test<span class="sy2">;</span><br />
<span class="sy1">+-----------+----------+----------+----------+</span><br />
<span class="sy1">|</span> <span class="kw1">Table</span> &nbsp; &nbsp; <span class="sy1">|</span> Op &nbsp; &nbsp; &nbsp; <span class="sy1">|</span> Msg_type <span class="sy1">|</span> Msg_text <span class="sy1">|</span><br />
<span class="sy1">+-----------+----------+----------+----------+</span><br />
<span class="sy1">|</span> test.test <span class="sy1">|</span> <span class="kw1">optimize</span> <span class="sy1">|</span> <span class="kw1">status</span> &nbsp; <span class="sy1">|</span> OK &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+-----------+----------+----------+----------+</span><br />
1 row <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span>15.85 sec<span class="br0">&#41;</span><br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> id &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> k <span class="sy1">|</span> <span class="kw1">data</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> 1999006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 1998006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 1997006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 1996006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 1995006 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
5 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>Затем добавил те самые два миллиона строк на место:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p32794">
        <div class="code mysql" id="p327code94">
mysql<span class="sy1">&gt;</span> <span class="kw2">INSERT</span> <span class="kw1">INTO</span> test <span class="kw1">SELECT</span> <span class="kw3">NULL</span><span class="sy2">,</span> k<span class="sy2">,</span> <span class="kw1">data</span> <span class="kw1">FROM</span> test<span class="sy2">;</span><br />
Query OK<span class="sy2">,</span> 2000000 rows affected <span class="br0">&#40;</span>2 <span class="kw22">min</span> 4.72 sec<span class="br0">&#41;</span><br />
Records: 2000000 &nbsp;Duplicates: 0 &nbsp;<span class="kw1">Warnings</span>: 0<br />
<br />
mysql<span class="sy1">&gt;</span> <span class="kw1">SELECT</span> <span class="sy1">*</span> <span class="kw1">FROM</span> test <span class="kw1">WHERE</span> k<span class="sy1">=</span>5 <span class="kw1">ORDER BY</span> <span class="kw1">data</span> <span class="kw1">DESC</span> <span class="kw1">LIMIT</span> <span class="nu0">5</span><span class="sy2">;</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> id &nbsp; &nbsp; &nbsp;<span class="sy1">|</span> k <span class="sy1">|</span> <span class="kw1">data</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
<span class="sy1">|</span> 4012000 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 4011999 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 4011998 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 4011997 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">|</span> 4011996 <span class="sy1">|</span> 5 <span class="sy1">|</span> ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4 <span class="sy1">|</span><br />
<span class="sy1">+---------+---+------------------------------------------+</span><br />
5 rows <span class="kw2">in</span> <span class="kw1">set</span> <span class="br0">&#40;</span><span class="nu0">0.00</span> sec<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>Что характерно: изменился порядок следования значений: теперь одинаковые значения <code>k</code> следуют друг за другом. Возможно, здесь "схитрил" оптимизатор&nbsp;&mdash;&nbsp;после <code>DELETE</code> перед <code>INSERT</code> я сделал <code>OPTIMIZE</code>.</p>
<p>Такие вот пироги&hellip; Так что заплачу за Интернет и пойду писать багрепорт.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/327-shit-happens/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/327-shit-happens/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Доступ к удалённому MySQL-серверу по SSH</title>
		<link>http://blog.sjinks.pro/mysql/121-access-to-remote-mysql-server-over-ssh/</link>
		<comments>http://blog.sjinks.pro/mysql/121-access-to-remote-mysql-server-over-ssh/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 14:10:18 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Администрирование]]></category>
		<category><![CDATA[Безопасность]]></category>
		<category><![CDATA[port forwarding]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=121</guid>
		<description><![CDATA[Использование перенаправления портов в SSH для доступа к удаленному серверу с локальной машины Как известно, в целях безопасности сервер MySQL по умолчанию открыт для доступа только с локальной системы. Поэтому, когда на сервере не установлен phpMyAdmin, а консольной версией клиента пользоваться просто неудобно (ненаглядно), приходится открывать доступ для удаленного пользователя. Но такое решение не самое [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/121-access-to-remote-mysql-server-over-ssh/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Использование перенаправления портов в <a href="http://blog.sjinks.pro/tag/ssh/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  ssh">SSH</a> для доступа к удаленному серверу с локальной машины</em></h2>
<p>Как известно, в целях безопасности сервер <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a> по умолчанию открыт для доступа только с локальной системы. Поэтому, когда на сервере не установлен phpMyAdmin, а консольной версией клиента пользоваться просто неудобно (ненаглядно), приходится открывать доступ для удаленного пользователя. Но такое решение не самое безопасное.</p>
<p>В таких случаях рекомендуется использовать методику, имеющую название <em><a href="http://blog.sjinks.pro/tag/port-forwarding/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  port forwarding">port forwarding</a></em> (перенаправление портов).<span id="more-121"></span></p>
<p>Например, чтобы обращение к <code>localhost:7000</code> было эквивалентно обращению на <code>remotehost:3306</code> с хоста <code>remotehost</code> от имени пользователя <code>user</code>, достаточно выполнить</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p12197">
        <div class="code bash" id="p121code97">
<span class="kw2">ssh</span> <span class="re5">-L</span> <span class="nu0">7000</span>:localhost:<span class="nu0">3306</span> user<span class="sy0">@</span>remotehost
        </div>
    </div>
</div>

<p>Синтакс имеет вид</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p12198">
        <div class="code bash" id="p121code98">
<span class="kw2">ssh</span> <span class="re5">-L</span> localport:targethost:targetport remoteuser<span class="sy0">@</span>remotehost
        </div>
    </div>
</div>

<p>При доступе к порту <code>localport</code> локальной машины будет осуществлено соединение с <code>remotehost</code> на <code>targethost:targetport</code>.</p>
<p>Теперь инструктируем локальный MySQL-клиент соединяться с <code>localhost:7000</code> и получаем доступ к MySQL на <code>remotehost:3306</code>.</p>
<p>Этот метод можно использовать не только для MySQL, но и для любых других серверов. Достоинства метода заключаются в том, что, во-первых, не надо открывать доступ к требуемому сервису из внешней сети, а во-вторых, соединение шифруется по протоколу SSH и, как следствие, является безопасным.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/121-access-to-remote-mysql-server-over-ssh/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/121-access-to-remote-mysql-server-over-ssh/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MySQL и скорость выполнения INSERT для разных типов таблиц</title>
		<link>http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/</link>
		<comments>http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 21:57:09 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[HEAP]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MyISAM]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[storage engine]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/</guid>
		<description><![CDATA[Сравнение скорости выполнения INSERT/INSERT DELAYED для таблиц типа HEAP (MEMORY), InnoDB и MyISAM Я сейчас работаю над очень интересным проектом, который, как надеется заказчик, составит серьёзную конкуренцию Google Analytics. Но речь не об этом. Разбираясь с архитектурой системы, я обнаружил весьма интересную деталь: 8&#160;гигабайт памяти сервера отдается под несколько таблиц типа HEAP. Так как HEAP-таблицы [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Сравнение скорости выполнения INSERT/INSERT DELAYED для таблиц типа <a href="http://blog.sjinks.pro/tag/heap/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HEAP">HEAP</a> (MEMORY), <a href="http://blog.sjinks.pro/tag/innodb/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  InnoDB">InnoDB</a> и <a href="http://blog.sjinks.pro/tag/myisam/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MyISAM">MyISAM</a></em></h2>
<p>Я сейчас работаю над очень интересным проектом, который, как надеется заказчик, составит серьёзную конкуренцию Google Analytics. Но речь не об этом. Разбираясь с архитектурой системы, я обнаружил весьма интересную деталь: 8&nbsp;гигабайт памяти сервера отдается под несколько таблиц типа HEAP. Так как HEAP-таблицы хранятся в исключительно в памяти, то операция вставки (INSERT) должна выполняться очень быстро, так как временн<em>ы</em>е затраты, связанные с перемещением головок диска и физической записью, отсутствуют. Я решил найти подтверждение этой теории. Google is your friend, и я довольно быстро нашел статью <a href="http://moncahier.canalblog.com/archives/2007/09/06/6119631.html">MySQL Engine INSERT speed</a>.<span id="more-44"></span></p>
<p>Меня несколько смутили результаты, приведённые автором:</p>
<ul>
<li><strong>MyISAM</strong> (с <code>DELAY_KEY_WRITE=ALL</code>): 33&nbsp;000&nbsp;INSERT/сек</li>
<li><strong>InnoDB</strong>: 24&nbsp;700&nbsp;INSERT/сек</li>
<li><strong>MEMORY</strong>: 64&nbsp;000&nbsp;INSERT/сек</li>
</ul>
<p>Смутило, в первую очередь, жуткое отставание InnoDB: хотя я не очень часто использовал данный тип таблиц, о его скорости я наслышан.</p>
<p>Первыми возникшими вопросами были:</p>
<ol>
<li>Какой тип вставки использовался для MyISAM/InnoDB-таблиц &mdash; <code>INSERT</code> или <code>INSERT DELAYED</code>?</li>
<li>Каким образом вставлялись данные &mdash; построчно или блочно (extended insert)?</li>
<li>Значение <code>AUTOCOMMIT</code> при работе с таблицей InnoDB.</li>
</ol>
<p>Об этом оставалось только гадать, поэтому я решил повторить этот эксперимент.</p>
<p><strong>Методика эксперимента:</strong><br />
Создаются три таблицы:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p44102">
        <div class="code mysql" id="p44code102">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test0`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`field`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><br />
<span class="br0">&#41;</span> <span class="kw1">TYPE</span><span class="sy1">=</span>HEAP<span class="sy2">;</span><br />
<br />
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test1`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`field`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><br />
<span class="br0">&#41;</span> <span class="kw1">TYPE</span><span class="sy1">=</span><span class="kw1">InnoDB</span><span class="sy2">;</span><br />
<br />
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`test2`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`field`</span> <span class="kw4">INTEGER</span> <span class="kw6">UNSIGNED</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><br />
<span class="br0">&#41;</span> <span class="kw1">TYPE</span><span class="sy1">=</span>MyISAM <span class="kw6">DELAY_KEY_WRITE</span><span class="sy1">=</span><span class="nu0">1</span><span class="sy2">;</span>
        </div>
    </div>
</div>

<p>Перед началом эксперимента выполнялась команда</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p44103">
        <div class="code mysql" id="p44code103">
<span class="kw1">SET</span> AUTOCOMMIT<span class="sy1">=</span><span class="nu0">0</span>
        </div>
    </div>
</div>

<p>Затем в цикле в таблицу вставлялись случайно сгенерированные данные (компьютер, на котором проводился эксперимент, был слабый, поэтому я ограничился тридцатью тысячами записями). После цикла выполнялся COMMIT. Скрипт выполнялся 10 раз, бралось среднее время.</p>
<p>Исходный текст скрипта:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p44104">
        <div class="code php" id="p44code104">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="kw3">set_time_limit</span><span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">function</span> microtime_float<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">list</span><span class="br0">&#40;</span><span class="re0">$usec</span><span class="sy0">,</span> <span class="re0">$sec</span><span class="br0">&#41;</span> <span class="sy0">=</span> <span class="kw3">explode</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="sy0">,</span> <span class="kw3">microtime</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>float<span class="br0">&#41;</span><span class="re0">$usec</span> <span class="sy0">+</span> <span class="br0">&#40;</span>float<span class="br0">&#41;</span><span class="re0">$sec</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
<br />
&nbsp; &nbsp; <span class="re0">$link</span> <span class="sy0">=</span> <span class="kw3">mysql_connect</span><span class="br0">&#40;</span><span class="st_h">'localhost'</span><span class="sy0">,</span> <span class="st_h">'root'</span><span class="sy0">,</span> <span class="st_h">''</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw3">mysql_select_db</span><span class="br0">&#40;</span><span class="st_h">'test'</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="re0">$schema</span> <span class="sy0">=</span> <span class="st0">&quot;CREATE TABLE `test` (`field` INTEGER UNSIGNED NOT NULL)&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$engines</span> <span class="sy0">=</span> <span class="kw1">array</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">' TYPE=HEAP'</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">' TYPE=InnoDB'</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">' DELAY_KEY_WRITE = 1 TYPE=MyISAM'</span><br />
&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="re0">$inserts</span> <span class="sy0">=</span> <span class="kw1">array</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">''</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">''</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'DELAYED'</span><span class="sy0">,</span><br />
&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;DROP TABLE IF EXISTS `test0`, `test1`, `test2`&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;SET AUTOCOMMIT=0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span><span class="sy0">=</span><span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">&lt;</span>count<span class="br0">&#40;</span><span class="re0">$engines</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="sy0">++</span><span class="re0">$i</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> <span class="sy0">=</span> <span class="kw3">preg_replace</span><span class="br0">&#40;</span><span class="st_h">'/`test`/'</span><span class="sy0">,</span> <span class="st0">&quot;`test<span class="es4">{$i}</span>`&quot;</span><span class="sy0">,</span> <span class="re0">$schema</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="re0">$engines</span><span class="br0">&#91;</span><span class="re0">$i</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="re0">$query</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;COMMIT&quot;</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$start</span> <span class="sy0">=</span> microtime_float<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$j</span><span class="sy0">=</span><span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$j</span><span class="sy0">&lt;</span><span class="nu0">30000</span><span class="sy0">;</span> <span class="sy0">++</span><span class="re0">$j</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$val</span> <span class="sy0">=</span> <span class="kw3">mt_rand</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;INSERT {<span class="es4">$inserts</span>[<span class="es4">$i</span>]} INTO `test<span class="es4">{$i}</span>` (`field`) VALUES(<span class="es4">{$val}</span>)&quot;</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">mysql_query</span><span class="br0">&#40;</span><span class="st0">&quot;COMMIT&quot;</span><span class="sy0">,</span> <span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$end</span> <span class="sy0">=</span> microtime_float<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="re0">$end</span> <span class="sy0">-</span> <span class="re0">$start</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="kw3">mysql_close</span><span class="br0">&#40;</span><span class="re0">$link</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p>У меня получились такие результаты (я привожу относительную &mdash; относительно таблиц типа HEAP &mdash; скорость):</p>
<table class="bordered" cellpadding="2" cellspacing="1">
<thead>
<tr>
<th>&nbsp;</th>
<th>HEAP</th>
<th>InnoDB</th>
<th>MyISAM</th>
</tr>
</thead>
<tbody align="right">
<tr>
<th>INSERT</th>
<td rowspan="2">1.000</td>
<td>1.277</td>
<td>1.162</td>
</tr>
<tr>
<th>INSERT DELAYED</th>
<td>2.125</td>
<td>0.998</td>
</tr>
</tbody>
</table>
<p>Эксперимент показал, что разница по скорости между INSERT DELAYED для таблицы MyISAM и INSERT для таблицы HEAP очень незначительна. Таблицы InnoDB действительно оказались медленнее, но не сильно. Большую роль здесь могла сыграть &laquo;слабость&raquo; тестового компьютера и значение переменной <code>innodb_flush_log_at_trx_commit</code>.  Вдобавок, MyISAM был сконфигурирован очень даже хорошо, в то время как InnoDB использовал практически значения по умолчанию (мне редко приходится пользоваться таблицами InnoDB, поэтому тонкой настройкой я не занимался). Тем не менее, результаты проведенного мной эксперимента совсем не согласуются с данными, приведёнными в исходной статье. Кто же из нас прав?</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/44-mysql-insert-speed-for-different-storage-engines/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Хранение PHP-сессий в базе данных</title>
		<link>http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/</link>
		<comments>http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 19:19:03 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[база данных]]></category>
		<category><![CDATA[сессия]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/</guid>
		<description><![CDATA[Подход, позволяющий хранить PHP-сессии в базе данных вместо файлов Начну сразу с причин, по которым я пишу эту статью. Я периодически просматриваю лог запросов, по которому люди попадают сюда, и вот один из запросов — хранить php сессию в mysql. Итак, как же хранить PHP-сессии в базе данных? На самом деле, в этом нет ничего сложного: в [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Подход, позволяющий хранить <a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">PHP</a>-сессии в базе данных вместо файлов</em></h2>
<p>Начну сразу с причин, по которым я пишу эту статью. Я периодически просматриваю <a href="http://blog.sjinks.pro/tag/log/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  лог">лог</a> запросов, по которому люди попадают сюда, и вот один из запросов — <q><strong>хранить php сессию в <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">mysql</a></strong></q>.</p>
<p>Итак, как же хранить PHP-сессии в базе данных?<span id="more-43"></span></p>
<p>На самом деле, в этом нет ничего сложного: в PHP есть одна полезная функция — <a href="http://www.php.net/manual/en/function.session-set-save-handler.php">session_set_save_handler</a> — которая и выполняет всю грязную работу:</p>
<blockquote cite="http://www.php.net/manual/en/function.session-set-save-handler.php"><strong>session_set_save_handler()</strong> sets the user-level session storage functions which are used for storing and retrieving data associated with a session. This is most useful when a storage method other than those supplied by PHP sessions is preferred. i.e. Storing the session data in a local database.</blockquote>
<p>Эта функция принимает шесть аргументов типа <code>сallback</code>:</p>
<ul>
<li><strong>open</strong> — вызывается при открытии/создании сессии;</li>
<li><strong>close</strong> — вызывается при закрытии сессии (например, чтобы приложение могло закрыть файл);</li>
<li><strong>read</strong> — чтение сессии;</li>
<li><strong>write</strong> — запись сессии;</li>
<li><strong>destroy</strong> — уничтожение сессии (<span class="codebox"><code class="php"><span class="kw3">session_destroy</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span>);</li>
<li><strong>gc</strong> — «сборка мусора»</li>
</ul>
<p>Все функции (кроме <code>read</code>) должны возвращать <span class="codebox"><code class="php"><span class="kw4">true</span></code></span>, если все прошло успешно и <span class="codebox"><code class="php"><span class="kw4">false</span></code></span> в противном случае.</p>
<p>Для хранения сессии у нас есть такая таблица:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p43109">
        <div class="code mysql" id="p43code109">
<span class="kw1">CREATE</span> <span class="kw1">TABLE</span> <span class="st0">`session`</span> <span class="br0">&#40;</span><br />
&nbsp; &nbsp; <span class="st0">`id`</span> CHARACTER<span class="br0">&#40;</span>32<span class="br0">&#41;</span> <span class="kw1">BINARY</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw1">PRIMARY KEY</span><span class="sy2">,</span> <span class="coMULTI">/* Session ID */</span><br />
&nbsp; &nbsp; <span class="st0">`expires`</span> <span class="kw4">INTEGER</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span> <span class="coMULTI">/* Время истекания сессии */</span><br />
&nbsp; &nbsp; <span class="st0">`session<span class="es1">_</span>data`</span> <span class="kw4">TEXT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span><span class="sy2">,</span> <span class="coMULTI">/* Данные, хранящиеся в сессии */</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">KEY</span><span class="br0">&#40;</span><span class="st0">`expires`</span><span class="br0">&#41;</span><br />
<span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p><strong>Один маленький нюанс:</strong> если в MySQL делать таблицу сессий типа <span class="codebox"><code class="mysql">MEMORY</code></span> (т.е. задать ей такой <a href="http://blog.sjinks.pro/tag/storage-engine/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  storage engine">storage engine</a>), то могут возникнуть проблемы с удалением записей при сборке мусора, ибо MEMORY <a href="http://blog.sjinks.pro/tag/storage-engine/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  storage engine">storage engine</a> не может использовать индексы для операций сравнения типа «больше»/«меньше».</p>
<p>Для абстракции от конкретного SQL-сервера, будем считать, что у нас имеется некий класс <span class="codebox"><code class="php">Persistent</code></span>, обладающий способностями загружать/сохранять данные в базу данных.</p>
<p>Таким образом, реализация класса <span class="codebox"><code class="php">Session</code></span> будет иметь следующий вид:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p43110">
        <div class="code php" id="p43code110">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'class.Persistent.php'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">class</span> Session <span class="kw2">extends</span> Persistent<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var string<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$id</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var int<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$expires</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var string<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$session_data</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var bool<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="re0">$m_new</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> __contruct<span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">parent</span><span class="sy0">::</span>__construct<span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">static</span> <span class="kw2">function</span> getTable<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> TABLE_SESSION<span class="sy0">;</span> <span class="co1">//константа, задающая имя таблицы сессий</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p>Пока все предельно просто. О переменной <span class="codebox"><code class="php"><span class="re0">$m_new</span></code></span> поговорим позже.</p>
<p>Теперь собственно реализация класса, <em>управляющего</em> сессиями:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p43111">
        <div class="code php" id="p43code111">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'class.Session.php'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">class</span> SessionManager<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var int<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">protected</span> <span class="re0">$life_time</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @var Session<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">protected</span> <span class="re0">$session</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @return SessionManager<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">function&amp;</span> instance<span class="br0">&#40;</span><span class="re0">$reinit</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">static</span> <span class="re0">$self</span> <span class="sy0">=</span> <span class="kw4">null</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">true</span> <span class="sy0">==</span> <span class="kw3">is_null</span><span class="br0">&#40;</span><span class="re0">$self</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$self</span> <span class="sy0">=</span> <span class="kw2">new</span> SessionManager<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$reinit</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">true</span> <span class="sy0">==</span> <span class="re0">$reinit</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">session_set_save_handler</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;open&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;close&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;read&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;write&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;destroy&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><span class="sy0">&amp;</span><span class="re0">$self</span><span class="sy0">,</span> <span class="st0">&quot;gc&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">register_shutdown_function</span><span class="br0">&#40;</span><span class="st_h">'session_write_close'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$self</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> open<span class="br0">&#40;</span><span class="re0">$save_path</span><span class="sy0">,</span> <span class="re0">$sess_name</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">life_time</span> <span class="sy0">=</span> <span class="kw3">intval</span><span class="br0">&#40;</span><span class="kw3">get_cfg_var</span><span class="br0">&#40;</span><span class="st_h">'session.gc_maxlifetime'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span> <span class="sy0">=</span> <span class="kw2">new</span> Session<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'id'</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=&gt;</span> <span class="br0">&#40;</span><span class="kw4">true</span> <span class="sy0">==</span> <span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$_COOKIE</span><span class="br0">&#91;</span><span class="re0">$sess_name</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> ? <span class="re0">$_COOKIE</span><span class="br0">&#91;</span><span class="re0">$sess_name</span><span class="br0">&#93;</span> <span class="sy0">:</span> <span class="kw3">session_id</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'expires'</span> &nbsp; &nbsp; &nbsp;<span class="sy0">=&gt;</span> <span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">life_time</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_data'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">m_new</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> close<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> read<span class="br0">&#40;</span><span class="re0">$sid</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span> <span class="sy0">=</span> Session<span class="sy0">::</span><span class="me2">load</span><span class="br0">&#40;</span><span class="st_h">'Session'</span><span class="sy0">,</span> <span class="re0">$sid</span><span class="sy0">,</span> 3600<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">false</span> <span class="sy0">==</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span> instanceof Session<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span> <span class="sy0">=</span> <span class="kw2">new</span> Session<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">array</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'id'</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=&gt;</span> <span class="br0">&#40;</span><span class="kw4">true</span> <span class="sy0">==</span> <span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$_COOKIE</span><span class="br0">&#91;</span><span class="kw3">session_name</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> ? <span class="re0">$_COOKIE</span><span class="br0">&#91;</span><span class="kw3">session_name</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#93;</span> <span class="sy0">:</span> <span class="kw3">session_id</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'expires'</span> &nbsp; &nbsp; &nbsp;<span class="sy0">=&gt;</span> <span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">life_time</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_data'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">m_new</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">m_new</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>string<span class="br0">&#41;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">session_data</span><span class="sy0">;</span> <span class="co1">//Явное приведение типа позволит избежать трудноуловимых ошибок</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> write<span class="br0">&#40;</span><span class="re0">$sid</span><span class="sy0">,</span> <span class="re0">$data</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">m_new</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">|=</span> <span class="br0">&#40;</span><span class="re0">$sid</span> <span class="sy0">!=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">id</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">id</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="re0">$sid</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">session_data</span> &nbsp;<span class="sy0">=</span> <span class="re0">$data</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">expires</span> &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">life_time</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$mode</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">true</span> <span class="sy0">==</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">m_new</span><span class="br0">&#41;</span> ? SAVE_INSERT <span class="sy0">:</span> SAVE_UPDATE<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="re0">$mode</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> destroy<span class="br0">&#40;</span><span class="re0">$sid</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">unset</span><span class="br0">&#40;</span><span class="re0">$_COOKIE</span><span class="br0">&#91;</span><span class="re0">$sid</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Session<span class="sy0">::</span><span class="me2">deleteMany</span><span class="br0">&#40;</span><span class="st_h">'Session'</span><span class="sy0">,</span> <span class="kw2">new</span> QueryCondition<span class="br0">&#40;</span><span class="kw1">array</span><span class="br0">&#40;</span><span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="re0">$sid</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> gc<span class="br0">&#40;</span><span class="re0">$max_time</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Session<span class="sy0">::</span><span class="me2">deleteMany</span><span class="br0">&#40;</span><span class="st_h">'Session'</span><span class="sy0">,</span> <span class="kw2">new</span> QueryCondition<span class="br0">&#40;</span><span class="st0">&quot;`expires` &lt; '&quot;</span> <span class="sy0">.</span> <span class="kw3">time</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;'&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co4">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @return Session<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function&amp;</span> getSession<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">session</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p><strong>Пример использования:</strong></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p43112">
        <div class="code php" id="p43code112">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="re0">$sm</span> <span class="sy0">=</span> <span class="sy0">&amp;</span>SessionManager<span class="sy0">::</span><span class="me2">instance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw3">session_start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p>Вкратце о <span class="codebox"><code class="php"><span class="re0">$m_new</span></code></span>. Дело в том, что ID сессии при ее открытии <em>может не совпадать</em> с ID при закрытии (иными словами, измениться в ходе выполнения скрипта). Один из способов — это использование функции <a href="http://www.php.net/manual/en/function.session-regenerate-id.php">session_regenerate_id()</a>. Поэтому при сохранении сессии важно знать, является ID новым или нет (если ID новый, то для сохранения будет использоваться <span class="codebox"><code class="mysql"><span class="kw2">INSERT</span></code></span>, если существующий — то <span class="codebox"><code class="mysql"><span class="kw1">UPDATE</span></code></span>; по большому счету можно обойтись одним <span class="codebox"><code class="mysql"><span class="kw2">REPLACE</span></code></span>, однако это не особо эффективное решение). Для этого при открытии сессии получаем текущий идентификатор сессии и сравниваем его с тем, который получаем при сохранении сессии (конечно, в этом простом случае можно было обойтись без лишней переменной, но в более сложных проектах она может понадобиться); в зависимости от их равенства/неравенства используем тот или иной метод сохранения данных.</p>
<p>Строка <span class="codebox"><code class="php"><span class="kw3">register_shutdown_function</span><span class="br0">&#40;</span><span class="st_h">'session_write_close'</span><span class="br0">&#41;</span></code></span> гарантирует, что <a href="http://blog.sjinks.pro/tag/session/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  сессия">сессия</a> будет сохранена (без нее в PHP4 у меня были случаи, когда <a href="http://blog.sjinks.pro/tag/session/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  сессия">сессия</a> не сохранялась).</p>
<p>О том, как прочитать данные из <span class="codebox"><code class="php">Session<span class="sy0">::</span><span class="me2">session_data</span></code></span>, можно прочитать в <a href="http://blog.sjinks.pro/php/6-php-sessions-unserialize/">этой статье</a>. Сразу отмечу, что PHP самостоятельно выполняет восстановление данных, которые ему передаются функцией <span class="codebox"><code class="php">SessionManager<span class="sy0">::</span><span class="me2">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span>, просто иногда бывают ситуации, когда сессию нужно восстановить вручную (подпатчить на лету).</p>
<p>При более глубоком изучении вопроса также будет полезна <a href="http://www.mysqlperformanceblog.com/2007/03/27/php-sessions-files-vs-database-based/">эта замечательная статья</a>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/43-storing-php-sessions-in-database/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Конвертирование базы данных MySQL из одного charset в другой</title>
		<link>http://blog.sjinks.pro/mysql/3-convert-mysql-database-from-one-charset-to-another/</link>
		<comments>http://blog.sjinks.pro/mysql/3-convert-mysql-database-from-one-charset-to-another/#comments</comments>
		<pubDate>Sun, 09 Mar 2008 21:30:02 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[utf8]]></category>
		<category><![CDATA[база данных]]></category>
		<category><![CDATA[преобразование]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/mysql/3-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b1%d0%b0%d0%b7%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-mysql-%d0%b8%d0%b7-%d0%be%d0%b4%d0%bd%d0%be/</guid>
		<description><![CDATA[Быстрый способ преобразования charset базы данных MySQL Недавно мне пришлось столкнуться с задачей перевода базы данных из одного charset в другой. Исходная база была в iso-8859-1, предстояло перевести её в utf-8. Задача усложнялась тем, что в исходной базе присутствовали символы из других языков (русский, испанский и, возможно, китайский). Погуляв по Интернету и поискав в Google, [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/3-convert-mysql-database-from-one-charset-to-another/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Быстрый способ преобразования charset базы данных <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  MySQL">MySQL</a></em></h2>
<p>Недавно мне пришлось столкнуться с задачей перевода базы данных из одного charset в другой. Исходная база была в iso-8859-1, предстояло перевести её в utf-8. Задача усложнялась тем, что в исходной базе присутствовали символы из других языков (русский, испанский и, возможно, китайский).<span id="more-3"></span></p>
<p>Погуляв по Интернету и поискав в Google, я нашёл несколько решений.</p>
<ol>
<li>Способ, который мне очень понравился&nbsp;&mdash;&nbsp;<a href="http://gentoo-wiki.com/TIP_Convert_latin1_to_UTF-8_in_MySQL" rel="nofollow">TIP: Convert latin1 to UTF-8 in MySQL</a><br />
Вкратце (я немного изменил команды для повышения эффективности работы скрипта):
          
<div class="codebox">
    <div class="the_code" style="" id="p3115">
        <div class="code bash" id="p3code115">
mysqldump <span class="re5">-uuser</span> <span class="re5">-ppassword</span> <span class="re5">--default-character-set</span>=latin1 <span class="re5">-n</span> <span class="re5">-K</span> <span class="re5">--skip-set-charset</span> <span class="re5">--skip-create-options</span> <span class="re5">--skip-extended-insert</span> <span class="re5">--compatible</span>=mysql40 --max_allowed_packet=64K dbname <span class="sy0">&gt;</span> latin_dump.sql<br />
iconv <span class="re5">-f</span> ISO-8859-1 <span class="re5">-t</span> UTF-8 latin_dump.sql <span class="sy0">&gt;</span> utf8_dump.sql<br />
mysql --max_allowed_packet=1M <span class="re5">-uuser</span> <span class="re5">-ppassword</span> <span class="re5">--default-character-set</span>=utf8 database_utf8 <span class="sy0">&lt;</span> utf8_dump.sql<br />
<span class="kw2">rm</span> <span class="re5">-f</span> <span class="sy0">*</span>.sql
        </div>
    </div>
</div>

<p>Идея состоит в том, что мы просто создаём дамп исходной базы, при этом указывая mysqldump, что никаких деклараций <code>CHARSET</code> и иже с ними указывать не надо, затем скармливаем полученный дамп iconv, который преобразует весь latin1 в <a href="http://blog.sjinks.pro/tag/utf8/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  utf8">utf8</a>, а затем преобразованный файл отдаём mysql  (при этом указываем, что <code>charset</code> по умолчанию у нас utf8).<br />
Из неприятного: не сработало <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Как оказалось, из-за того, что cPanel создал базу (которая database_utf8) с <code>DEFAULT CHARSET latin1</code>. К счастью, лечится просто:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p3116">
        <div class="code mysql" id="p3code116">
<span class="kw1">ALTER</span> <span class="kw2">DATABASE</span> <span class="st0">`database<span class="es1">_</span>utf8`</span> CHARACTER <span class="kw1">SET</span> <span class="st0">'utf8'</span><span class="sy2">;</span><br />
<span class="kw1">ALTER</span> <span class="kw2">DATABASE</span> <span class="st0">`database<span class="es1">_</span>utf8`</span> <span class="kw10">COLLATE</span> <span class="st0">'utf8<span class="es1">_</span>general<span class="es1">_</span>ci'</span><span class="sy2">;</span>
        </div>
    </div>
</div>

</li>
<li>Экзотика (ссылку, к сожалению, потерял): идея состоит в том, что каждый столбец (CHAR, VARCHAR, TEXT etc) преобразуется сначала в BLOB (при этом меняется только тип столбца и ничего более), а затем BLOB преобразуется в исходный тип, но уже с новым charset. Я как представлю себе, сколько там менять&hellip;</li>
<li>Супер экзотика: <a href="http://www.oreillynet.com/onlamp/blog/2006/01/turning_mysql_data_in_latin1_t.html" rel="nofollow">Turning MySQL data in latin1 to utf8 utf-8</a>. Без комментариев <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Видимо, человеку очень надо было преобразовать базу <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ol>
<p>И на закуску самый простой метод:</p>
<pre lang="mysql">ALTER TABLE `table_name` <a href="http://blog.sjinks.pro/tag/convert/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  convert">CONVERT</a> TO CHARACTER SET 'utf8';</pre>
<p>Ибо как сказано в <a href="http://dev.mysql.com/doc/refman/5.0/en/alter-table.html" title="ALTER TABLE Syntax" trl="nofollow">официальной документации</a>:</p>
<blockquote cite="http://dev.mysql.com/doc/refman/5.0/en/alter-table.html">If you want to change the table default character set and all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:
<pre lang="mysql">ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;</pre>
<p>For a column that has a data type of VARCHAR or one of the TEXT types, CONVERT TO CHARACTER SET will change the data type as necessary to ensure that the new column is long enough to store as many characters as the original column. For example, a TEXT column has two length bytes, which store the byte-length of values in the column, up to a maximum of 65,535. For a latin1 TEXT column, each character requires a single byte, so the column can store up to 65,535 characters. If the column is converted to utf8, each character might require up to 3 bytes, for a maximum possible length of 3 × 65,535 = 196,605 bytes. That length will not fit in a TEXT column's length bytes, so MySQL will convert the data type to MEDIUMTEXT, which is the smallest string type for which the length bytes can record a value of 196,605. Similarly, a VARCHAR column might be converted to MEDIUMTEXT.</p></blockquote>
<p><strong>А мораль такова:</strong> если ничего не получается, прочтите, наконец, документацию! <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/mysql/3-convert-mysql-database-from-one-charset-to-another/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/mysql/3-convert-mysql-database-from-one-charset-to-another/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

