Ужасы таксономии в WordPress

Vladimir
Опубликовано в: WordPress

12,000 запросов для удаления одной категории

Внутренняя реализация управления таксономиями в WordPress — это просто кошмар какой-то. Мало того, что код написан в процедурном стиле (использование ООП помогло бы решить некоторые проблемы с производительностью, которые иначе можно решить только глобальными переменными), он к тому же очень плохо масштабируется.

Я взял свежую дефолтную инсталляцию WordPress 2.8-bleeding, сгенерировал тестовый контент и пошел искать недоработки и проблемы с производительностью. Одну из них я нашел очень быстро: при попытке удалить категорию, в которой была 1,001 ночь запись.

На неслабом сервере это заняло около 20 секунд и… более 12,000 запросов (да-да, двенадцати тысяч, я количеством ноликов, увы, не ошибся).

Лог запросов (application/x-gzip, 75.1 КиБ)
Лог запросов (text/html, 2.5 МиБ)

А всё почему? Из-за одного магического foreach в wp_delete_term():

[-]
View Code PHP
    foreach ( (array) $objects as $object ) {
        $terms = wp_get_object_terms($object, $taxonomy, 'fields=ids');
        if ( 1 == count($terms) && isset($default) )
            $terms = array($default);
        else
            $terms = array_diff($terms, array($term));
        $terms = array_map('intval', $terms);
        wp_set_object_terms($object, $terms, $taxonomy);
    }

Куда уж проще: выбрать ID всех объектов, связанных с данной таксономией:

[-]
View Code MySQL
SELECT DISTINCT tr.object_id
FROM wp_term_taxonomy AS tt INNER JOIN wp_term_relationships AS tr USING(term_taxonomy_id)
WHERE tr.term_id = 'TERM ID HERE' AND tr.taxonomy = 'TAXONOMY NAME HERE'

Затем удалить терм к едрене фене и жукам майским:

[-]
View Code MySQL
DELETE
FROM wp_term_taxonomy AS tt LEFT JOIN wp_term_relationships AS tr USING(term_taxonomy_id)
WHERE tr.term_id = 'TERM ID HERE' AND tr.taxonomy = 'TAXONOMY NAME HERE'

Затем вставить дефолтное значение терма для тех объектов, которые выпали из таксономии: вычитаем из результата, полученного в первом запросе, результат запроса SELECT object_id FROM wp_term_relationship WHERE object_id IN ("список из первого запроса"). Для полученного результата выполнить один большой INSERT:

[-]
View Code MySQL
INSERT INTO wp_term_relationships VALUES
('OBJECT_ID_1', 'DEFAULT_TERM_TAXONOMY_ID', 0), /* ... */ ('OBJECT_ID_N', 'DEFAULT_TERM_TAXONOMY_ID', 0)

После чего сделать UPDATE wp_term_taxonomy SET `count` = `count` + 'количество строк, затронутых INSERT' WHERE term_taxonomy_id = 'DEFAULT_TERM_TAXONOMY_ID'.

Причём если дефолтное значение терма не задано, то достаточно просто одного DELETE.

В результате получаем пять запросов вместо 12,000, улучшенную производительность и меньше мусора. За кадром осталась очистка инсулинового кэша WordPress, но идея понятна. Вот только жаль, что оно увидит свет очень нескоро.

Добавить в закладки

Связанные записи

9
Июнь
2009

Комментарии к статье «Ужасы таксономии в WordPress» (13)  »

  1. Vladimir says:

    Кому интересно: этой проблеме уже целых два года. Обсуждение ведётся в багтрекере.

    • Алексей says:

      Ну зато 10 часов назад
      # status changed from new to accepted

      Что-то я подозреваю что стоит подождать 2.9, может там будет какой-то прогресс, в плане оптимизации производительности.

      • Vladimir says:

        Ну так пока кого-нибудь не пнёшь, никто шевелиться не будет. Хотя судя по возрасту бага, я сомневаюсь, что в 2.9 сделают — есть и трехлетние баги :-)

        В плане быстродействия — я в WordPress разочаровался. С каждым новым релизом он все медленнее по скорости и громаднее по размеру. Если бы я писал CMS, в ядре было бы все самое необходимое, а вся требуемая функциональность бы расширялась за счет плагинов.

  2. Vanilla Man says:

    Я прямо удивился, после прочтения. Во многих англоязычных обзорах 2.8 как раз отмечалась оптимизация производительности.. Очень жаль, если это не так..

  3. Efrosinich says:

    Чем дальше движется прогресс тем всё больщие награмождения мы себе придумываем, но от необходимого никуда неденешса

    • Vladimir says:

      Мой горячо любимый сплоггер, пожалуйста, научись пользоваться разметкой (закрывать тэги) и выучи, наконец, грамматику и синтаксис русского языка. Спасибо.

  4. -torin- says:

    Да уж.. К версии вордпресс 3.0 придется переезжать на что-нибудь полегче. Возможно даже Битрикс :)

  5. Wave says:

    Не сочтите за рекламу, но видели ли вы MaxSite CMS? Её делают, устав от тормозов и ограничений вордпресса, и уже сейчас она очень во многом лучше оного.
    Вот сравнение :)

    • Vladimir says:

      Видел. Но мы используем (нашу сильно патченную) версию WordPress в довольно серьёзных приложениях, и заменять её чем-то другим просто не готовы.

      MaxSite CMS мне очень не нравится с её подходом к безопасности. Особенно функция mso_checkreferer(). Во-первых, она криво работает со всякими фаерволами, которые блокируют Referer, а во-вторых, она абсолютно не защищает от подмены Referer. Её реализация при должном навыке атакующего никак не защитит от CSRF (ради которого всё и делалось).

      Я детально не заглядывал в код, но у меня есть подозрения по поводу возможных XSS-уязвимостей (XSS в традиционном понимании).

      В MaxCMS большой напряг с плагинами — в WordPress с этим проще.

      К тому же у меня есть свои сомнения по поводу её использования на сильно нагруженных сайтах (поддержка транзакций, репликации, возможность масштабирования).

      Ну и заниматься поддержкой нескольких систем мне хочется меньше всего — если что идёт не так, меня заказчики по ночам будят :-)

    • -torin- says:

      Wave, вот у вас блог на MaxSite CMS. И как оно для обычного блогера, не програмиста? Тяжело привыкать после wp?

      • Wave says:

        Для обычного блоггера, не программиста, обычно мало разницы, на чём вести блог. Что поставят, или что получится поставить. Хоть друпал, хоть нейтрино. МаксСайт — это примерно пятая-седьмая система, которую я щупал. Плюс опыт в php и то, что за развитием системы я следил с самого начала. Так что для меня никаких проблем не было.
        Логичность (понятность) и удобность админки и вообще структуры сайта гораздо выше чем у той же джумлы или друпала. Но не хватает некоторых аяксовых возможностей админки вордпресса. Например, редактирование заголовков постов не заходя в редактирование самих постов.
        А так — большинство новичков хвалят за удобство и понятность. Но бывает, что некоторые не могут найти очевидных вещей, например, как сменить шаблон.

        P.s.
        В MaxCMS большой напряг с плагинами — в WordPress с этим проще.
        Цитата: «Ну да, если сравнивать абсолютное количество, то WordPress безусловный лидер. Правда есть один немаловажный фактор: плагины к WordPress в основном плодятся от безысходности. Возьмем очень простой пример: разместить в сайдбаре счетчик и какой-нибудь php-код.

        [пояснение]

        Ну и будет ли блогер в MaxSite CMS бегать и искать другие плагины для вывода рубрик или размещения счетчиков?»

        • Vladimir says:

          плагины к WordPress в основном плодятся от безысходности

          С этим не соглашусь. На мой взгляд, в ядро не стоит запихивать все подряд — смысл туда помещать то, чем будут пользоваться 10% пользователей? Достаточно развитой системы фильтров/хуков. Но это моё ИМХО.

          Возьмем очень простой пример: разместить в сайдбаре счетчик и какой-нибудь php-код.

          Текстовые виджеты никто не отменял. А размещать произвольный PHP-код — это небезопасно: если через уязвимость ядра/темы/плагина злоумышленник сможет получить доступ к базе, он в этот произвольный PHP-код может запихнуть свой шелл-код. Который потом будет непросто обнаружить.

  6. Ал says:

    Ваши записи произвели на меня огромное впечатление, заставили думать по-другому. Продолжайте свои творческие поиски, а я буду следовать за Вами!

Подписаться на RSS-ленту комментариев к статье «Ужасы таксономии в WordPress» Trackback URL: http://blog.sjinks.org.ua/wordpress/575-horror-of-taxonomy-in-wordpress/trackback/

Оставить комментарий к записи «Ужасы таксономии в WordPress»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя