<?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; NextGen Gallery</title>
	<atom:link href="http://blog.sjinks.pro/tag/nextgen-gallery/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sjinks.pro</link>
	<description>Quod scripsi, scripsi</description>
	<lastBuildDate>Thu, 02 Sep 2010 17:48:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Еще одна оптимизация NextGen Gallery</title>
		<link>http://blog.sjinks.pro/wordpress/patches/703-yet-another-nextgen-gallery-optimization/</link>
		<comments>http://blog.sjinks.pro/wordpress/patches/703-yet-another-nextgen-gallery-optimization/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 21:19:54 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Патчи]]></category>
		<category><![CDATA[NextGen Gallery]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[оптимизация]]></category>
		<category><![CDATA[патч]]></category>
		<category><![CDATA[плагин]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=703</guid>
		<description><![CDATA[Минус один UPDATE при каждом обращении к блогу Плагин NextGen Gallery имеет одну неприятную особенность: при каждом обращении к блогу выполняется обновление (UPDATE в терминах MySQL) таблицы wp_options. Хотя для «средних» блогов это не критично, для хорошо посещаемых ресурсов это плохо по ряду причин: Обновление таблицы wp_options сбрасывает кэш запросов MySQL к таблице wp_options, что [...]<hr/>
<p>© 2008–2010 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>

<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a
href="http://blog.sjinks.pro/wordpress/patches/703-yet-another-nextgen-gallery-optimization/">источник</a> <strong>обязательно</strong>.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Минус один UPDATE при каждом обращении к блогу</em></h2>
<p>Плагин <a href="http://blog.sjinks.pro/tag/nextgen-gallery/" class="st_tag internal_tag" rel="tag" title="Posts tagged with NextGen Gallery">NextGen Gallery</a> имеет одну неприятную особенность: при каждом обращении к блогу выполняется обновление (<span class="codebox"><code class="mysql"><span class="kw1">UPDATE</span></code></span> в терминах <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Posts tagged with MySQL">MySQL</a>) таблицы <code>wp_options</code>. Хотя для «средних» блогов это не критично, для хорошо посещаемых ресурсов это плохо по ряду причин:</p>
<ol>
<li>Обновление таблицы <code>wp_options</code> сбрасывает кэш запросов <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Posts tagged with MySQL">MySQL</a> к таблице <code>wp_options</code>, что приводит к необходимости реального выполнения запросов на выборку данных (с учётом огромного количества записей — благодаря всяким разным плагинам — это лишний трафик между PHP и <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Posts tagged with MySQL">MySQL</a>).</li>
<li>Выполнение операции обновления таблицы при использовании MyISAM приводит к блокировке таблицы; при высокой посещаемости это приводит к вынужденному ожиданию освобождения таблицы и негативно сказывается на нагрузке и производительности.</li>
<li>При использовании плагинов объектного кэширования каждый вызов <span class="codebox"><code class="php">update_option<span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> приводит к необходимости обновления и записи кэша; обновление файлового объектного кэша приводит к лишним обращениям к диску (которых на виртуальных серверах лучше избегать).</li>
<li>В конце концов, это лишний запрос, который <strong>не является необходимым</strong>.</li>
</ol>
<p><span id="more-703"></span></p>
<p>Использование плагина <a href="http://blog.sjinks.pro/wordpress-plugins/sqlmon/">MySQL Monitor</a> показывает:</p>
<ul>
<li><strong>Запрос:</strong>
          
<div class="codebox">
    <div class="the_code" style="" id="p7034">
        <div class="code mysql" id="p703code4">
<span class="kw1">UPDATE</span> <span class="st0">`wp<span class="es1">_</span>options`</span> <span class="kw1">SET</span> <span class="st0">`option<span class="es1">_</span>value`</span> <span class="sy1">=</span> <span class="st0">'a:3:{i:0;b:0;s:29:<span class="es0">\&quot;</span>nextgen-gallery/nggallery.php<span class="es0">\&quot;</span>;a:2:{i:0;s:9:<span class="es0">\&quot;</span>nggLoader<span class="es0">\&quot;</span>;i:1;s:9:<span class="es0">\&quot;</span>uninstall<span class="es0">\&quot;</span>;}...}'</span> <span class="kw1">WHERE</span> <span class="st0">`option<span class="es1">_</span>name`</span> <span class="sy1">=</span> <span class="st0">'uninstall<span class="es1">_</span>plugins'</span>
        </div>
    </div>
</div>

</li>
<li><strong>Трасса вызовов:</strong>
          
<div class="codebox">
    <div class="the_code" style="" id="p7035">
        <div class="code text" id="p703code5">
wp-includes/wp-db.php, 830 (DbProfile::query)<br />
wp-includes/functions.php, 533 (wpdb::update)<br />
wp-includes/plugin.php, 608 (update_option)<br />
wp-content/plugins/nextgen-gallery/nggallery.php, 80 (register_uninstall_hook)<br />
wp-content/plugins/nextgen-gallery/nggallery.php, 429 (nggLoader::nggLoader)<br />
wp-settings.php, 566 (include_once)<br />
wp-config.php, 84 (require_once)<br />
wp-load.php, 30 (require_once)<br />
wp-blog-header.php, 12 (require_once)<br />
index.php, 17 (require)
        </div>
    </div>
</div>

</li>
</ul>
<p>Говоря простым языком, <a href="http://blog.sjinks.pro/tag/nextgen-gallery/" class="st_tag internal_tag" rel="tag" title="Posts tagged with NextGen Gallery">NextGen Gallery</a> <strong>при каждой загрузке <a href="http://blog.sjinks.pro/tag/wordpress/" class="st_tag internal_tag" rel="tag" title="Posts tagged with WordPress">WordPress</a></strong> регистрирует функцию деинсталляции плагина. Таким образом, если мы имеем 25,000 показов страниц в день, это выливается в 25,000 (относительно медленных) запросов <code>UPDATE</code> к базе.</p>
<p>Проблема решается очень просто: вызов функции <span class="codebox"><code class="php">register_uninstall_hook</code></span> переносится из конструктора <span class="codebox"><code class="php">nggLoader<span class="sy0">::</span><span class="me2">nggLoader</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> (файл <code>nextgen-gallery/nggallery.php</code>) в самый конец функции <span class="codebox"><code class="php">nggLoader<span class="sy0">::</span><span class="me2">activate</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code></span> (за строку <span class="codebox"><code class="php">delete_option<span class="br0">&#40;</span> <span class="st_h">'ngg_update_exists'</span> <span class="br0">&#41;</span><span class="sy0">;</span></code></span>).</p>
<p>Получаем простой патч:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p7036">
        <div class="code diff" id="p703code6">
--- nggallery.php.old &nbsp; 2009-11-23 22:06:09.000000000 +0200<br />
<span class="re4">+++ nggallery.php &nbsp; &nbsp; &nbsp; <span class="nu0">2009</span>-<span class="nu0">11</span>-<span class="nu0">23</span> <span class="nu0">22</span>:07:<span class="nu0">55.000000000</span> +0200</span><br />
<span class="re6">@@ -<span class="nu0">76</span>,<span class="nu0">9</span> +<span class="nu0">76</span>,<span class="nu0">6</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; register_activation_hook<span class="br0">&#40;</span> $this-&gt;plugin_name, array<span class="br0">&#40;</span>&amp;$this, 'activate'<span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; register_deactivation_hook<span class="br0">&#40;</span> $this-&gt;plugin_name, array<span class="br0">&#40;</span>&amp;$this, 'deactivate'<span class="br0">&#41;</span> <span class="br0">&#41;</span>;&nbsp; <br />
&nbsp;<br />
<span class="re7">- &nbsp; &nbsp; &nbsp; // Register a uninstall hook to remove all tables &amp; option automatic</span><br />
<span class="re7">- &nbsp; &nbsp; &nbsp; register_uninstall_hook<span class="br0">&#40;</span> $this-&gt;plugin_name, array<span class="br0">&#40;</span>'nggLoader', 'uninstall'<span class="br0">&#41;</span> <span class="br0">&#41;</span>;</span><br />
<span class="re7">-</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; // Start this plugin once all other plugins are fully loaded<br />
&nbsp; &nbsp; &nbsp; &nbsp; add_action<span class="br0">&#40;</span> 'plugins_loaded', array<span class="br0">&#40;</span>&amp;$this, 'start_plugin'<span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span class="re6">@@ -<span class="nu0">376</span>,<span class="nu0">6</span> +<span class="nu0">373</span>,<span class="nu0">8</span> @@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; // remove the update message<br />
&nbsp; &nbsp; &nbsp; &nbsp; delete_option<span class="br0">&#40;</span> 'ngg_update_exists' <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; // Register a uninstall hook to remove all tables &amp; option automatic</span><br />
<span class="re8">+ &nbsp; &nbsp; &nbsp; register_uninstall_hook<span class="br0">&#40;</span> $this-&gt;plugin_name, array<span class="br0">&#40;</span>'nggLoader', 'uninstall'<span class="br0">&#41;</span> <span class="br0">&#41;</span>;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; function deactivate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        </div>
    </div>
</div>

<hr/>
<p>© 2008–2010 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>

<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a
href="http://blog.sjinks.pro/wordpress/patches/703-yet-another-nextgen-gallery-optimization/">источник</a> <strong>обязательно</strong>.</p>
	<h4>Связанные записи</h4>
	<ul class="st-related-posts">
	<li><a href="http://blog.sjinks.pro/php/179-patch-for-wp-wassup-151/" title="Патч для WP WassUp 1.5.1 (Июнь 1, 2008)">Патч для WP WassUp 1.5.1</a> (1)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/patches/13-patch-for-wp-codebox-for-valid-xhtml/" title="Патч для WP CodeBox для Valid XHTML (Март 11, 2008)">Патч для WP CodeBox для Valid XHTML</a> (5)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/patches/201-patch-for-wassup-16/" title="Патч для WassUp 1.6 (Июнь 20, 2008)">Патч для WassUp 1.6</a> (2)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/patches/86-patch-for-wassup-15-for-wordpress/" title="Патч для WassUp 1.5 for WordPress (Апрель 13, 2008)">Патч для WassUp 1.5 for WordPress</a> (2)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/patches/89-patch-for-subscribe-to-comments-212/" title="Патч для Subscribe to Comments 2.1.2 (Апрель 13, 2008)">Патч для Subscribe to Comments 2.1.2</a> (16)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/wordpress/patches/703-yet-another-nextgen-gallery-optimization/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Увеличение производительности плагина NextGen Gallery</title>
		<link>http://blog.sjinks.pro/wordpress/572-improving-nextgen-gallery-performance/</link>
		<comments>http://blog.sjinks.pro/wordpress/572-improving-nextgen-gallery-performance/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 10:27:11 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[NextGen Gallery]]></category>
		<category><![CDATA[плагин]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=572</guid>
		<description><![CDATA[Добавляем необходимые индексы в таблицу В случае, если галереи содержат несколько тысяч изображений, в зависимости от мощности сервера и посещаемости сайта могут возникнуть проблемы с производительностью, связанные с неоптимальностью индексов в таблице wp_ngg_pictures. Проявляется это в том, что при отображении любой галереи MySQL приходится полностью сканировать таблицу wp_ngg_pictures. Например: EXPLAIN SELECT SQL_CALC_FOUND_ROWS tt.*, t.* FROM [...]<hr/>
<p>© 2008–2010 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>

<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a
href="http://blog.sjinks.pro/wordpress/572-improving-nextgen-gallery-performance/">источник</a> <strong>обязательно</strong>.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Добавляем необходимые индексы в таблицу</em></h2>
<p>В случае, если галереи содержат несколько тысяч изображений, в зависимости от мощности сервера и посещаемости сайта могут возникнуть проблемы с производительностью, связанные с неоптимальностью индексов в таблице <code>wp_ngg_pictures</code>.<span id="more-572"></span></p>
<p>Проявляется это в том, что при отображении любой галереи <a href="http://blog.sjinks.pro/tag/mysql/" class="st_tag internal_tag" rel="tag" title="Posts tagged with MySQL">MySQL</a> приходится полностью сканировать таблицу <code>wp_ngg_pictures</code>.</p>
<p>Например:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p57211">
        <div class="code mysql" id="p572code11">
<span class="kw1">EXPLAIN</span><br />
<span class="kw1">SELECT</span> <span class="kw1">SQL_CALC_FOUND_ROWS</span> tt.<span class="sy1">*</span><span class="sy2">,</span> t.<span class="sy1">*</span><br />
<span class="kw1">FROM</span> wp_ngg_gallery <span class="kw1">AS</span> t <span class="kw1">INNER</span> <span class="kw1">JOIN</span> wp_ngg_pictures <span class="kw1">AS</span> tt <span class="kw1">ON</span> t.gid <span class="sy1">=</span> tt.galleryid<br />
<span class="kw1">WHERE</span> t.gid <span class="sy1">=</span> 3 <span class="kw10">AND</span> tt.exclude<span class="sy1">&lt;&gt;</span>1<br />
<span class="kw1">ORDER BY</span> tt.sortorder <span class="kw1">ASC</span>
        </div>
    </div>
</div>

          
<div class="codebox">
    <div class="the_code" style="" id="p57212">
        <div class="code text" id="p572code12">
+----+-------------+-------+-------+---------------+---------+---------+-------+--------+----------------+<br />
| id | select_type | table | type &nbsp;| possible_keys | key &nbsp; &nbsp; | key_len | ref &nbsp; | rows &nbsp; | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br />
+----+-------------+-------+-------+---------------+---------+---------+-------+--------+----------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| t &nbsp; &nbsp; | const | PRIMARY &nbsp; &nbsp; &nbsp; | PRIMARY | 8 &nbsp; &nbsp; &nbsp; | const | &nbsp; &nbsp; &nbsp;1 | Using filesort |<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| tt &nbsp; &nbsp;| ALL &nbsp; | NULL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| NULL &nbsp; &nbsp;| NULL &nbsp; &nbsp;| NULL &nbsp;| &nbsp;11700 | Using where &nbsp; &nbsp;|<br />
+----+-------------+-------+-------+---------------+---------+---------+-------+--------+----------------+
        </div>
    </div>
</div>

<p>Исправляется ситуация путём добавления ключа по столбцам <code>galleryid</code> и <code>sortorder</code> в таблицу <code>wp_ngg_pictures</code>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p57213">
        <div class="code mysql" id="p572code13">
<span class="kw1">ALTER</span> <span class="kw1">TABLE</span> <span class="st0">`wp<span class="es1">_</span>ngg<span class="es1">_</span>pictures`</span> <span class="kw1">ADD</span> <span class="kw1">KEY</span> <span class="br0">&#40;</span><span class="st0">`galleryid`</span><span class="sy2">,</span> <span class="st0">`sortorder`</span><span class="br0">&#41;</span>
        </div>
    </div>
</div>

<p>После этого <span class="codebox"><code class="mysql"><span class="kw1">EXPLAIN</span></code></span> покажет значительно лучшую картину:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p57214">
        <div class="code text" id="p572code14">
+----+-------------+-------+-------+---------------+-----------+---------+-------+------+-------------+<br />
| id | select_type | table | type &nbsp;| possible_keys | key &nbsp; &nbsp; &nbsp; | key_len | ref &nbsp; | rows | Extra &nbsp; &nbsp; &nbsp; |<br />
+----+-------------+-------+-------+---------------+-----------+---------+-------+------+-------------+<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| t &nbsp; &nbsp; | const | PRIMARY &nbsp; &nbsp; &nbsp; | PRIMARY &nbsp; | 8 &nbsp; &nbsp; &nbsp; | const | &nbsp; &nbsp;1 | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| tt &nbsp; &nbsp;| ref &nbsp; | galleryid &nbsp; &nbsp; | galleryid | 8 &nbsp; &nbsp; &nbsp; | const | &nbsp; 59 | Using where |<br />
+----+-------------+-------+-------+---------------+-----------+---------+-------+------+-------------+
        </div>
    </div>
</div>

<p>Как видим, использование правильного индекса позволяет избежать файловой сортировки; к тому же, из таблицы <code>wp_ngg_pictures</code> сразу выбираются только нужные данные (59 строк против 11,700 строк).</p>
<hr/>
<p>© 2008–2010 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>

<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a
href="http://blog.sjinks.pro/wordpress/572-improving-nextgen-gallery-performance/">источник</a> <strong>обязательно</strong>.</p>
	<h4>Связанные записи</h4>
	<ul class="st-related-posts">
	<li><a href="http://blog.sjinks.pro/wordpress/plugins/190-wp-file-cache-replacement-for-wp_object_cache-with-persistent-caching/" title="WP File Cache: замена WP_Object_Cache с поддержкой долговременного кэширования (Июнь 12, 2008)">WP File Cache: замена WP_Object_Cache с поддержкой долговременного кэширования</a> (16)</li>
	<li><a href="http://blog.sjinks.pro/wordpress-plugins/sqlmon/" title="SQLMon: мониторинг запросов MySQL (Ноябрь 23, 2009)">SQLMon: мониторинг запросов MySQL</a> (6)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/575-horror-of-taxonomy-in-wordpress/" title="Ужасы таксономии в WordPress (Июнь 9, 2009)">Ужасы таксономии в WordPress</a> (16)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/tips-and-tricks/349-secrets-of-update_postmeta_cache/" title="Секреты update_postmeta_cache() (Октябрь 1, 2008)">Секреты update_postmeta_cache()</a> (5)</li>
	<li><a href="http://blog.sjinks.pro/wordpress/patches/707-all-in-one-seo-pack-optimization/" title="Оптимизация All in One SEO Pack (Ноябрь 25, 2009)">Оптимизация All in One SEO Pack</a> (9)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/wordpress/572-improving-nextgen-gallery-performance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
