Производительность Joomla на больших объемах контента

    image

    Joomla очень плохо переваривает базу данных даже с несколькими тысячами статей в таблице _content. При нескольких десятках тысяч запросы в базу стандартных модулей типа mod_articles_popular могут зависать на секунды.

    Всё дело в ACL (Access Control List) — политике контроля доступа. Проверка законности доступа пользователя к материалам занимает свыше 98% времени выполнения запроса.

    Тем временем, есть сайты, которым это не нужно. Например, новостной сайт, показывающий в левой колонке модуль «Самые читаемые статьи» всем подряд. Что делать в этом случае? Отключить проверку ACL в helper.php модуля. Благо это не трудно — просто комментируем строку:

    $model->setState('filter.access', $access);

    Давайте посмотрим на результат. Включаем в админке отладку, смотрим в дебаг-информации запрос в базу данных этого модуля. Вот он без ACL:

    Запрос в БД mod_articles_popular без ACL
    Время запроса: 18.84 ms После последнего запроса: 6.38 ms Память запроса: 0.012 MB Память до запроса: 7.288 MB Выбрано строк: 5
    
    SELECT a.id, a.title, a.alias, a.introtext, a.fulltext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias, 
      CASE WHEN a.modified = '0000-00-00 00:00:00' THEN a.created ELSE a.modified END as modified, a.modified_by, uam.name as modified_by_name,
      CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END as publish_up,a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, a.language,  LENGTH(a.fulltext) AS readmore,
      CASE WHEN badcats.id is not null THEN 0 ELSE a.state END AS state,c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias,
      CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author,ua.email AS author_email,parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias,ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count,c.published, 
      CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published
    
      FROM jos_content AS a
    
      LEFT JOIN jos_categories AS c 
      ON c.id = a.catid
    
      LEFT JOIN jos_users AS ua 
      ON ua.id = a.created_by
    
      LEFT JOIN jos_users AS uam 
      ON uam.id = a.modified_by
    
      LEFT JOIN jos_categories as parent 
      ON parent.id = c.parent_id
    
      LEFT JOIN jos_content_rating AS v 
      ON a.id = v.content_id
    
      LEFT 
      OUTER JOIN (SELECT cat.id as id 
      FROM jos_categories AS cat JOIN jos_categories AS parent 
      ON cat.lft BETWEEN parent.lft 
      AND parent.rgt 
      WHERE parent.extension = 'com_content' 
      AND parent.published != 1 
      GROUP BY cat.id ) AS badcats 
      ON badcats.id = c.id
    
      WHERE 
    
    
      CASE WHEN badcats.id is null THEN a.state ELSE 0 END = 1 
      AND a.catid IN (9,11,12,13,15,21,24,25) 
      AND a.publish_up >= DATE_SUB('2018-04-30 03:27:24', INTERVAL 60 DAY)
    
      ORDER BY a.hits DESC 
      LIMIT 5


    Вот с ACL:

    Запрос в БД mod_articles_popular c ACL
    Время запроса: 972.79 ms После последнего запроса: 3.96 ms Память запроса: 0.012 MB Память до запроса: 7.378 MB Выбрано строк: 5
    
    SELECT a.id, a.title, a.alias, a.introtext, a.fulltext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias, 
      CASE WHEN a.modified = '0000-00-00 00:00:00' THEN a.created ELSE a.modified END as modified, a.modified_by, uam.name as modified_by_name,
      CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END as publish_up,a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, a.language,  LENGTH(a.fulltext) AS readmore,
      CASE WHEN badcats.id is not null THEN 0 ELSE a.state END AS state,c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias,
      CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author,ua.email AS author_email,parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias,ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count,c.published, 
      CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published
    
      FROM jos_content AS a
    
      LEFT JOIN jos_categories AS c 
      ON c.id = a.catid
    
      LEFT JOIN jos_users AS ua 
      ON ua.id = a.created_by
    
      LEFT JOIN jos_users AS uam 
      ON uam.id = a.modified_by
    
      LEFT JOIN jos_categories as parent 
      ON parent.id = c.parent_id
    
      LEFT JOIN jos_content_rating AS v 
      ON a.id = v.content_id
    
      LEFT 
      OUTER JOIN (SELECT cat.id as id 
      FROM jos_categories AS cat JOIN jos_categories AS parent 
      ON cat.lft BETWEEN parent.lft 
      AND parent.rgt 
      WHERE parent.extension = 'com_content' 
      AND parent.published != 1 
      GROUP BY cat.id ) AS badcats 
      ON badcats.id = c.id
    
      WHERE a.access IN (1,1,2,3,6) 
      AND c.access IN (1,1,2,3,6) 
      AND 
      CASE WHEN badcats.id is null THEN a.state ELSE 0 END = 1 
      AND a.catid IN (9,11,12,13,15,21,24,25) 
      AND a.publish_up >= DATE_SUB('2018-04-30 03:36:50', INTERVAL 60 DAY)
    
      ORDER BY a.hits DESC 
      LIMIT 5


    Разница всего в двух проверках в WHERE клаузе:

    a.access IN (1,1,2,3,6)  AND c.access IN (1,1,2,3,6)

    а также во времени выполнения запроса в первой строке: 19 миллисекунд и 973 миллисекунды. 98%. На базе данных с 5000 статей. На мощном сервере хостера. Это цена широко разрекламированного Joomla ACL.

    Но, оказывается, разработчики этого фреймворка прекрасно в курсе данного момента, и встроили в ее админку возможность отключить проверку ACL. Но сделали это так, чтобы никто не догадался.

    Опция находится в «Общие настройки» -> «Материалы», внизу первого таба «Материалы», называется «Показывать ссылки неавторизованным». Расшифровывается всплывающей подсказкой как: "Если установлено значение Да, то ссылки на просмотр полного текста материалов смогут видеть все пользователи, в том числе, не прошедшие авторизацию, но для просмотра полного текста система потребует ввести логин и пароль".

    Вроде бы к делу не относится, но выполняет именно то, что надо — отменяет проверку ACL для всех модулей (которые используют эту политику). Переменная $access в $model->setState('filter.access', $access) — это именно этот чекбокс (с обратным/восклицательным знаком). О его существовании подсказал один из разработчиков этого CMS-а.

    Кому нужно, могут оживить свою Джумлу.

    Примечание: Как выяснилось из испытаний и обсуждений в комментариях, подобное торможение на данном запросе с проверкой ACL происходит нерегулярно и не детерминированно. Выборка без индекса с вычисляемыми полями в условии с использованием дисковых операций при больших объемах данных на моих тестах иногда не помещалась в памяти СУБД, иногда помещалась — в этом случае вышеуказанные запросы с ACL были примерно на 50% дольше. Возможно это зависит от окружения сервера.
    Поделиться публикацией

    Комментарии 77

      +1
      … этого CMS-а

      CMS — не КМС, она женского рода

        0
        В английском языке мужской и женский рода могут быть только у одушевленных предметов. Неодушевленные и младенцы — средний (it).
          0

          Ну да, конечно.
          А почему тогда, ну например, по отношению к кораблям применяются местоимения she и her?

            +1
            На названия кораблей посмотрите
              0

              например?

              0
              Это исключение. Грубо говоря для англичан корабль == лодка. Оно she.
                0
                Традиция, сэр! Вон во французском языке слово «весна» вообще мужского рода.
                +1
                Текст на русском языке.
                –1

                Чтобы понять род Joomla, достаточно как в школе, поставить вопрос:


                • "Joomla — оно моё." Значит среднего рода.
                • "Wordpress — оно моё." Тоже среднего рода

                Почти все CMS, которые доступны сейчас среднего рода, даже если кто-то вам говорит, что "эта вот женского", а "эта вот мужского", на деле же они все среднего.

                  +5

                  CMS — система управления контентом, то есть система — она.
                  Joomla — среднего среднего, хотя бы из-за этимологии слова.

                    0
                    а VIP по-вашей схеме это он или она?
                      0
                      VIP это person, а person это they с тех пор как политкорректность стала частью западной культуры.
                        –1
                        Тогда и CMS-ы — they. Из поликорректности. Как часть западной культуры.
                    +1
                    :facepalm:

                    Ух, языческие боги и макаронный монстр! Они среднего рода потому, что есть одно слово, вернее субстанция, пахучая и несъедобная, которая их весьма точно харакатеризует.
                    Тоже спойлер нужен?

                  +2

                  Вот читаю про открытие это и думаю, что об этом со времен Joomla 3 говорят.
                  Реализация ACL всегда была скорей минусом нежели плюсом Joomla, конечно хорошо, что он есть, но он избыточен и при это не гибок, тем более его реализация для материалов Joomla.
                  Ну а если говорить про материалы, они ни когда не проектировались под большие нагрузки, хотя вроде в вашем примере и не должно быть больших нагрузок, есть подозрение, что у вас изначально не так, что-то с базой (допустим неудачная миграция базы), так как 5000 материалов для Joomla это пшик, проблемы начинаются, когда больше 20 тысяч, что редко бывает на обычном сайте.
                  А так сама Joomla может сколько угодно контента переваривать, все зависит от того, как напишешь компонент.

                    0
                    А что может быть не так с базой? )))
                    Всё почти стандартное, «из под коробки», левого софта не стоит.

                    Честно говоря, я сам удивился, такой задержке — почти в секунду. Когда материалов было около 30 тысяч, такая задержка была. Но иногда и до 6 секунд, помню, прыгало (как-то недетерминированно, видимо зависит от иной нагрузки на сервер). Возможно и тут флуктуация такая случилась. Но как минимум 400 мс стопудово будет.

                    Не в абсолютном значении дело, а в относительном. И компонент тут ни при чем — запрос происходит в модуле. Я не спец по реляционным базам, поэтому не буду давать оценку, почему так происходит и как это исправить в корне. Но лекарство указал. О нем многие знают знатоки джумлы, но я в свое время кучу времени и нервов (хостер тыкал пальцем на загрузку сервера и прайслист доп.услуг) потратил на эту фигню, так что пусть будет документально оформлено тут)
                      +2
                      А что может быть не так с базой? )))

                      Банально индексы отвалились.
                        +2

                        Как сказали выше индексы отвалились.
                        Неудачная миграция с Joomla 1.0/1.5/2.5.
                        Неудачная миграция в рамках линейки 3, когда они добавили поддержку utf8mb4.


                        Вариантов много — это лишь самые распространенные.
                        Вы думаете, что из коробки самые лучшие расширения стоят? На самом деле из коробки расширения больше, как пример реализации API стоит рассматривать.

                          0
                          «Из коробки» имелось ввиду, что это чистая джумла с официального сайта, правильно заполняемая данными, без импортов/экспортов данных и прочего, что могло бы нарушить изначальную целостность схемы
                          +1
                          А что может быть не так с базой?

                          перестройте индексы, проапдейтите статистику, а потом сравните будет ли такая же разница. Речь про таблицы, участвующие в запросе и их индексах.
                          Если всё останется так же медленно (большие шансы, что нет) — то тогда надо строить query plan для случаев с и без ACL и сравнивать это даст ответ на вопрос почему база перестала работать быстро.
                            0
                            Спасибо, проверю.
                              0
                              Вы правы, это был индекс. Но как-то странно.

                              Сделал на этих двух таблицах optimize, и время запроса резко упало — в пределах 30 мс. Начал тестировать, обновлять страницу — три раза было 25-30 мс, и тут на четвертый 360 мс. На пятый — 400 мс. Опять делаю optimize — время снова падает. Много рефрешил, но уже не смог отловить поломку.

                              В среднем, запрос c ACL был процентов на 50% по времени тяжелей с рабочими индексами, чем без ACL. Но что опять произошло с индексами через небольшое время после перестройки и почему?
                                0
                                Не уверен в своём высказывании, прошу сразу простить, но может у вас индексы в отведенную БД память не влазят? Смотрели конфигурацию?
                                  0
                                  Всё на хостинге. Качеством и техническим уровнем сервиса пока был доволен.
                                  0
                                  Возможно это не ваш случай, но _обычно_ индексы получаются перекошенные, если идут вместе подряд DDL и DML запросы. Т.е. менять схему на лету с данными.
                                  Или вот — тоже простой способ выстрелить себе в ногу — это удалить все старые данные таблицы и быстренько наполнить другие данные, для которых старая статистика работать не будет. Например были все записи с одним и тем же значением в проиндексированном поле — такой индекс игнорируется по статистике, а потом вы наполняете новыми, где эта колонка содержит или уникальные или почти уникальные данные — если индекс по-прежнему игнорируется (статистика велит), то всё, запросы будут тормозить.
                                  База данных — штука не глупая, обычно она сам обновляет статистику, но иногда почему-то не обвновляет, или забывает обновить
                                    0
                                    Давайте конкретно мой тестируемый случай рассматривать. Вчера были запросы большие, я сделал optimize на _content и _categories. Время запросов стало маленьким на 3 минуты, и затем опять большим. Снова optimize, снова маленькое и уже надолго. Утром сегодня проверяю — опять большое (300мс-1200мс). Причем, за ночь в _content ничего не добавлялось.

                                    Из того, что я делал с БД раньше (давно) — чистка _assets вот этим способом и удалял руками из _content данные.
                            0
                            Глупый вопрос, но нельзя ли для ACL воткнуть кэширование? По идее это такие вещи, которые не так часто меняются и отлично подпадают под возможность кэширования(я про ACL). Механизмов хватает — Redis/Memcache/(да даже тупое кэширование файловое) должно улучшить на порядки производительность. Конечно, это приведет к модификации исходного кода Joomla(что не хорошо в плане последующих апгрейдов)… Но даже не знаю стоит ли из бетонных блоков пытаться слепить детский песочный домик или слегка допилить напильником то, что уже есть…
                              0
                              Чисто из академического интереса: покажите пожалуйста explain длинного запроса.
                                0
                                image
                                Время опять стало большим (1100мс)
                                  0
                                  скорее всего — using temporary и using filesort — вот что тормозит
                                  Плюс к этому вопрос — почему ключ такой длинный? Что там такое в ключе аж на 203 байт?
                                  Похоже индекс не влазит в память и был вытеснен. Вам нужно увеличить память для кеширования или поменять диск на более быстрый
                                    0
                                    То есть во время выполнения этого запроса на большой таблице при создании temporary table слетают индексы у _content, правильно я понимаю?
                                      0
                                      Во время выполнения этого запроса сервер получает 201 тысячу строк от storage engine частично без использования индексов а затем все это весело размешивает, используя дисковую сортировку.
                                        0
                                        в таблице большой ключ cat_idx — 203 байта на каждую запись. Что в этом ключе? Из-за того что он большой, а памяти выдено мало — данные сортируются во временном файле. Поэтому и тормоза.

                                        Что касается быстрых и медленных периодов — сравните query plan когда быстро и когда медленно.
                                          0
                                          Я думаю по сравнению с остальными проблемами это слезы.
                                      0
                                      и sort buffer тоже увеличить
                                        0
                                        База на хостинге, я ничего не могу. Hostland.
                                        0
                                        1. Нужно увеличивать размер памяти под сортировку. filesort это вообще за пределами добра и зла. А тут их аж два. Это дисковые операции. И если 25 строк еще не проблема, то вот 4022 уже могут вполне ею быть.
                                        2. В остальном explain без отрезанных колонок читать невозможно. Можно глянуть в личке если смущает светить именами таблиц.

                                        ЗЫ group by без агрегатных функций это чтобы сложней читать?) это distinct
                                        ЗЫЗЫ а вообще на беглый взгляд с запросом все очень плохо.

                                          0
                                          1. Это полный explain запроса. Я ничего не обрезал.
                                          2. Это сгенерированный sql-запрос стандартного модуля джумлы. Оценивать его эффективность можно, но менять нет смысла. В смысле, только если переписать модуль, (что давно есть в планах сделать).
                                          3. Ваш запрос попробовал. 30 мс, но и мои тяжелые с утра запросы тоже стали выполняться быстро. Причем
                                          4. с таблицами я ничего не делал, индексы не перестраивал.

                                          5. Вопрос: это из-за shared хостинга такое? Недерминированное выделение памяти под сортировку и временную таблицу?
                                            0
                                            1. Это phpMyAdmin так выводит? Ндаааа, тогда лучше конечно в консоли.
                                            2. Пичалька. Ибо за такие запросы нужно по руками роялем. Я внес чисто косметические изменения: как раз с расчетом на то чтобы в генераторе поменять было легко. По идее я бы еще часть в подзапрос вывел и перелопатил серьезно.
                                            3. Для него важна на скорость а explain. И для исходного запроса его бы сейчас выполнить, должна быть иная картина.

                                            4.5 Под сортировку выделения памяти как раз строго соответствует конфигу. Увеличение этого показателя ускорить запросы где есть файлсорт значительно но общей проблемы не решит. Запросы подобные этому это извращенное издевательство над mysql оптимизатором и память тут весьма критична.

                                            Чтобы ручками не лазить можно взять mysqltuner.pl и запустить. Он выдает много интересных циферок и общая картина как правило сразу видна. Не знаю только насколько этот совет применим к вашему хостингу.
                                              +1
                                              Не знаю только насколько этот совет применим к вашему хостингу.

                                              Вангую что никак.
                                                0
                                                Почему? SSH есть, python тоже. Да нормальный хостинг. Не в деньгах дело — с ним проще, чем VDS настраивать и за всем следить.
                                                0
                                                Запросы стали опять долгие. Ваш — быстрый.

                                                Смотрите, конкретно этот запрос сам по себе сейчас не важен. Он в принципе общий для модулей джумла (схема построения запроса).

                                                В основной статье тут оказалась допущена ошибка — многократное увеличение времени выполнения запроса происходит не всегда. Нужно понять (оценить), насколько эта проблема имеет общий характер. Относится ли она только ко мне, только к shared hosting, насколько она детерминирована. Ну и корень проблемы, желательно.

                                                Правильно я понимаю, что при общих настройках MySQL и достаточно большом количестве данных в таблице _content, она может возникнуть у достаточно большого неопределенного числа пользователей джумлы?
                                                  0
                                                  Смотрите, конкретно этот запрос сам по себе сейчас не важен.

                                                  Я его хотел использовать для оценки масштабов катастрофы.

                                                  Нужно понять (оценить), насколько эта проблема имеет общий характер.

                                                  Выборка без индекса с вычисляемыми полями в условии да еще с использованием дисковых операций это очень плохо.

                                                  Относится ли она только ко мне, только к shared hosting, насколько она детерминирована.

                                                  Вы вынуждаете меня гадать без полных данных) Если бы вы могли показать explain второго запроса. А еще лучше обоих из консоли и результат работы скрипта что я выше линканул я бы сказал точнее.
                                                  Но на вскидку, в зависимости от наличия памяти, такие проблемы будут у всех. Большое количество памяти и ssd хранилище будут нивелировать сей эффект.

                                                  Ну и корень проблемы, желательно.

                                                  Дебильные запросы.
                                                  Оператор in это вообще своеобразная штука.

                                                  На вскидку, самое простое: добавить индекс по времени и поставить условие по нему первым (или в подзапрос вынести), это уже облегчит жизнь небольшим сайтам. Убрать кейс из условия к чертям, он там не нужен абсолютно. Ну и ACL должен работать по маскам или хешу но не через in, но при малом количестве данных по идее уже не будет играть столь серьезную роль.
                                                    0
                                                    Этот модуль делает следующее — показывает 5 самых читаемых статей их определенных категорий. То есть, по сути, вот это:
                                                    Запрос без ACL
                                                    SELECT *
                                                      FROM jos_content AS a, jos_categories AS c 
                                                      WHERE c.id = a.catid
                                                      AND a.catid IN (9,11,12,13,15,21,24,25) 
                                                      AND a.publish_up >= DATE_SUB('2018-04-30 03:36:50', INTERVAL 60 DAY)
                                                      ORDER BY a.hits DESC 
                                                      LIMIT 5


                                                    Всё остальное — навороты SQL генератора джумлы для универсальности.
                                                    Я просто перепишу модуль с этим запросом, поэтому заморачиваться на него не хочу, но, в принципе, качественно и количественно оценить неэффективность запросов джумлы задача интересная. Может, попозже.
                                                    Кстати, этот запрос быстрый (10 мс), но using filesort всё равно есть
                                                      0
                                                      Я догадался уже)
                                                      Конечно есть, индекса по датам то нет как минимум. У нормального запроса должны быть указано using index. А у вас скорее всего using where,using filesort.

                                                      Я не уверен будет ли mysql использовать индекс по cat_id, но самый простой эксперимент над таким запросом: поставьте условия по датам первым и добавьте индекс (publish_up, cat_id, hits) ну или хоты бы по publish_up

                                                      Всё остальное — навороты SQL генератора джумлы для универсальности.

                                                      И его можно очень сильно облегчить если грамотно организовать подзапрос. Даже без оптимизаций.
                                                      Какая универсальность в том же left outer join к таблице content я честно не догадываюсь.
                                                      А приколы вроде case которое спокойно разворачивается в нормальное условия практически разрывают оптимизатор пополам.
                                                        +1
                                                        Вот выдержки:
                                                        The presence of «Using where» in the Extra column in EXPLAIN indicates that the MySQL server is applying a WHERE filter after the storage engine returns the rows.


                                                        When you issue a query that is covered by an index (an index-covered query), you’ll see «Using index» in the Extra column in EXPLAIN.
                                                        When MySQL can’t use an index to produce a sorted result, it must sort the rows itself. It can do this in memory or on disk, but it always calls this process a filesort, even if it doesn’t actually use a file.


                                                        When sorting a join, MySQL may perform the filesort at two stages during the query execution. If the ORDER BY clause refers only to columns from the first table in the join order, MySQL can filesort this table and then proceed with the join. If this happens, EXPLAIN shows «Using filesort» in the Extra column. Otherwise, MySQL must store the query’s results into a temporary table and then filesort the temporary table after
                                                        the join finishes. In this case, EXPLAIN shows «Using temporary; Using filesort» in the Extra column. If there’s a LIMIT, it is applied after the filesort, so the temporary table and the filesort can be very large.
                                                          0
                                                          Да, правильно. Когда долгие запросы. у меня «Using temporary; Using filesort». Когда быстрые, «Using where; Using filesort», но это тоже не правильно, как я понимаю.

                                                          Будет время я все-таки замеряю разницу в скорости стандартного решения и оптимизированного под конкретные запросы. Хотя не понятно, как запись в temporary table оценивать — оно то есть, то нет на одном запросе и с одними данными. А влияние оказывает критическое.
                                                            0
                                                            Поймите, дело не только во флагах.
                                                            Возьмем ваш explain. К сожалению таки без остальных колонок я могу ошибиться но вроде там четкая иерархия судя по запросу.
                                                            Итак там написано примерно вот что: просматриваем 4022*2*25 строк, причем раз стоит using where значит мы их именно выбираем, а затем весело с огоньком размешиваем всю эту веселую кучу из 201 тысячи строк. Где то в процессе мы еще создаем временную таблицу. А под конец веселья мы все это сортируем на диске.

                                                            А если вспомнить что в конце нам нужно 5 строк то совсем прикольно. Поэтому даже если тупо в лоб отсеять большую часть результатов в самом начале (при помощи индексов как я выше написал или вынести в подзапрос) то количество строк сразу же уменьшается очень существенно.

                                                            но это тоже не правильно, как я понимаю.

                                                            using where трактуется как реплика storage engine в духе: я вообще не понял что ты от меня хочешь, вот держи строки и сам разбирайся.

                                                            Будет время я все-таки замеряю разницу в скорости стандартного решения и оптимизированного под конкретные запросы.

                                                            Зачем?) Если уж есть желание провести эксперимент, попробуйте как я чуть выше посоветовал с индексом. Ну или задайте уточняющие вопросы, постараюсь ответить.
                                                              0
                                                              Зачем?)

                                                              Хочу подойти к этому вопросу обстоятельно. А то любители джумлы у меня с кармы на этой статье -5 сняли, надо будет аргументировать им свою позицию. Есть план ))

                                                              По запросу, думаю, индекс по publish_up и сперва подзапрос по нему же (в моем варианте SQL). После него останется уже немного статей.
                                                                0
                                                                А то любители джумлы у меня с кармы на этой статье -5 сняли

                                                                Любителям джумлы я выше много красноречивых эпитетов про запросы оставил с аргументацией, пусть вчитываются) Если серьезно то история как и с битриксом, с такими запросами все будет работать либо на мощных серверах либо на незначимых объемах контента.

                                                                По запросу, думаю, индекс по publish_up и сперва подзапрос по нему же (в моем варианте SQL). После него останется уже немного статей.

                                                                угу и вот это уже замерять.

                                                                Могу в принципе помочь из академического интереса найти оптимальный вариант если дадите консольку.
                                                  0
                                                  Попробуйте кстати explain extended
                                                  0
                                                  Хостер ответил, что sort_buffer_size = 4194304 байт (4 Мб).
                                                  0
                                                  Попробуйте этот запросик
                                                  SELECT *
                                                  FROM jos_content AS a
                                                  LEFT JOIN jos_categories AS c 
                                                    ON c.id = a.catid
                                                  LEFT JOIN jos_users AS ua 
                                                    ON ua.id = a.created_by
                                                  LEFT JOIN jos_users AS uam 
                                                    ON uam.id = a.modified_by
                                                  LEFT JOIN jos_categories as parent 
                                                    ON parent.id = c.parent_id
                                                  LEFT JOIN jos_content_rating AS v 
                                                    ON a.id = v.content_id
                                                  LEFT OUTER JOIN (SELECT cat.id as id 
                                                                   FROM jos_categories AS cat 
                                                                   JOIN jos_categories AS parent 
                                                                     ON cat.lft BETWEEN parent.lft AND parent.rgt 
                                                                   WHERE parent.extension = 'com_content' AND 
                                                                         parent.published != 1 
                                                                   GROUP BY cat.id ) AS badcats 
                                                    ON badcats.id = c.id
                                                  WHERE badcats.id is null AND 
                                                        a.state=1 AND
                                                        a.publish_up >= DATE_SUB('2018-04-30 03:36:50', INTERVAL 60 DAY) AND
                                                        a.access IN (1,1,2,3,6) AND 
                                                        a.catid IN (9,11,12,13,15,21,24,25)
                                                  ORDER BY a.hits DESC 
                                                  LIMIT 5


                                                  Хотя смысл аутер джоина от меня ускользает, но пусть будет для чистоты эксперимента.
                                                    0
                                                    Хотя смысл аутер джоина от меня ускользает, но пусть будет для чистоты эксперимента.

                                                    Его еще год назад убрали.


                                                    Да и вообще много чего за 1,5 года изменилось в ядре

                                                    0
                                                    Возможно, оптимизатор какое-то время собирает статистику, а потом решает, что filesort и temporary быстрее будет. Сравните explain сразу после optimize и когда опять начнёт тормозить.
                                                  0
                                                  В Joomla > 1.6 есть таблица assets. Если проводилась миграция контента или еще какая вставка контента прямо в базу, то могла быть нарушена структура таблицы assets. Эта неправильно сформированная таблица может очень сильно тормозить.
                                                  Когда-то немного вникал в этот вопрос, собственно, погуглите «joomla assets table slow down». Вот, кстати, для начала docs.joomla.org/Fixing_the_assets_table.
                                                  Не знаю, имеет ли это отношение к вашему случаю. Но Joomla достаточно сложна и то что вы сделали какие-то действия и после это кажутся очевидными какие-то выводы, то всё может быть далеко не так как кажется, а просто были задействованы механизмы, о которых вы даже не подозревали (например, почистился или создался какой-о кэш, Джумловской или серверный и т. п. бог знает что ещё).
                                                    0
                                                    Никаких миграций не было, но я чистил эту таблицу вот по этой схеме
                                                    Давно чистил. После этого вчера вот перестраивал индексы и опять все слетело.
                                                    0

                                                    А ещё при сохранении материала в админке Joomla делает столько же апдейтов в базу, сколько там было материалов: https://konservs.com/post/179.

                                                      0

                                                      Кроме ээээ??? это статья ничего не вызывает. Я не исключаю, что так могло быть на указанном сайте, однако очень интересно почему он не обновлялся. Сдается из-за каких то кривых расширений или хаков движка, но можете попробовать на чистом движке Joomla, такого не должно быть, так как это бессмысленное действие.
                                                      Кстати в этом блоге в основном информация про Joomla 2.5, учитывая, то что линейка Joomla 3 вышла 6 лет назад и за это время ее основательно переписали, сложно говорить о применимости этих всех рассуждений.

                                                        0
                                                        С чего утверждение про Joomla 2.5 и нечистый движок?
                                                          0

                                                          Joomla 2.5 быстрее, чем Joomla 3, но я очень мало сайтов видел на Joomla 2.5.28, в основном они почему-то, либо на 2.5.8 (одна из самых кривых версий в этой линейке), либо на 2.5.14 и самая главная особенность 2.5 ее очень много хакали, так как было еще живо поколение разработчиков, которые выросли на Joomla 1.5, где и правда без хаков ядра было тяжело.
                                                          А мой комент, к тому, что с большой долей вероятности на чистой установке последней Joomla история из блога не воспроизведется.

                                                            0
                                                            Joomla сильно тормозит на большом количестве статей — это известный факт, поднимался на форумах не раз.
                                                            Торможения из-за не эффективных запросов и ACL — это тоже факт.
                                                            Статья моя об этом. Если у вас все хорошо — значит эта проблема вас не касается.
                                                              0
                                                              Извиняюсь.
                                                              Что-то я не заметил, что разговор про статью konservs.com/post/179. и все перепутал
                                                          0

                                                          Да, сайт был на Joomla 2.5. Однако кастомных расширений почти не было. И всё которые были — это модули. И проблема была в админ. панели, в com_content.


                                                          Я глянул быстренько на GitHub — код пересортировки всей таблицы все ещё остался: https://github.com/joomla/joomla-cms/blob/staging/administrator/components/com_content/models/article.php


                                                          Будет время — гляну детальнее, подниму чистую Joomla, попробую воссоздать проблему. Для чистоты эксперимента.

                                                            0

                                                            Попробуйте ради интереса, просто переписывать всю таблицу после сохранения смысла нет, собственно вы своей статье об этом говорили.

                                                        0

                                                        Обо все по порядку


                                                        1. Пост называется "Производительность Joomla на больших объемах контента" однако в самом посте речь идет об одном модуле одного компонента. Что само по себе не корректно.
                                                        2. В результатах тестирования не указанная конфигурация сервера. Хотя сами подсчеты идут в % и мс.
                                                        3. Сам совет и результат. Как писал в п1. Речь о конкретном модулей и компоненте. Вот зайдет почитать человек у которого на сайте com_content не используется, или этот модуль не выводиться, и будет думать а почему же решение не помогло.
                                                        4. Когда суппорт хостинга только и делает что тыкает вас в плайс лист с требованиями сменить тариф, такой хостинг стоит менять.

                                                        Теперь по делу.
                                                        Если уж мы говорим о проблеме с модулями, то скажу так. Самое простое это взять и написать свой, занимает это 2-3 часа. Сразу с оптимальным запросом и прочими полезными плюшками. Заодно и ajax погрузку итемов можно добавить, а то что посетителю вечно на 5 самых популярных пялиться.
                                                        Отображать итемы всем посетителям далеко не лучшее решение.
                                                        Кстати если вы оптимизируете модуль "из коробки" милости просим на github против ни кто не будет, наверное =).


                                                        Тоже относиться и к компонентам, как верно заметил zikkuratvk, com_content с легкостью справляется с 15-20к материалов, даже при хорошей посещаемости. Дальше начинаются проблемы. Поэтому если мы говорим о большом количестве итемов, то лучше озаботиться написание своего компонента, выкинув при этом все не нужное.


                                                        Что же касается ACL в целом, с этим действительно есть проблемы, но их решение не стоит в приоритете, ну или всем просто лень туда соваться, да и пропихнуть PR с полной переработкой ACL без поддержки будет крайне не просто.


                                                        Кстати говоря com_fields жрет очень не мало. Поэтому если поля не нужны отключить их лишним не будет.


                                                        P.S Лично я com_content не очень жалую ибо он годиться разве что для небольшого блога.

                                                          0
                                                          По порядку:
                                                          1. 1. Речь не об одном модуле, а о генераторе sql запросов джумлы — то есть, по большому счету, о всех стандартных модулях и (предположительно) большинстве модулей из магазина джумла. Описанный модуль взят для примера, и к компоненту он не привязан, кстати.
                                                          2. 2. Конфигурация не играет роли, если все дело в не оптимизированном sql
                                                          3. 3. См. п.1 + данный модуль на моем лично сайте выводится всегда, и не единожды. И он ключевой на фронтэнде — блок последних новостей
                                                          4. 4. Это была фигура речи, мой хостер очень толерантно и понимающе относился к временным мои переборам, за что я плачу ему лояльностью


                                                          По делу:
                                                          Так и сделал, переписал ВСЕ модули, причем, не как модули, а, грубо говоря, подключаемый свой код в шаблоне, заняло, действительно, несколько часов. Код стал лаконичный и быстрый. От джумлы теперь только com_content. И с него бы слез, но джумла все-равно останется для админки и компонента поиска, загрузки и обработки информации. Ajax в планах.

                                                          com_content у меня легко справлялся с 50к+ статьями, если отключить ACL. Дело не в нем, а в джумловском генераторе sql для модулей и плагинов. Он генерит жуткий код.
                                                            0
                                                            Исходя из этого вашего ответа можно легко сделать вывод о вашей компетенции.

                                                            из магазина джумла.

                                                            В магазине joomla продают футболки.

                                                            Описанный модуль взят для примера, и к компоненту он не привязан, кстати.

                                                            Смотрим вот на эти строки
                                                            github.com/joomla/joomla-cms/blob/staging/modules/mod_articles_popular/helper.php#L14
                                                            github.com/joomla/joomla-cms/blob/staging/modules/mod_articles_popular/helper.php#L33

                                                            Так и сделал, переписал ВСЕ модули, причем, не как модули, а, грубо говоря, подключаемый свой код в шаблоне, заняло, действительно, несколько часов.

                                                            Писать запрос в бд в шаблоне даешь дубль запросов =) Еще небось без JDatabase

                                                            И с него бы слез, но джумла все-равно останется для админки и компонента поиска, загрузки и обработки информации.

                                                            Вот тут даже ничего сказать не могу. для админки? у вас уже что com_content = всей админ. Поиск? — com_search как бы ищет не только в com_content да и расширяется плагинами.
                                                          +1

                                                          Так стоп это вообще какая Joomla? (Только сейчас пригляделся к запросу внимательно)


                                                          badcats убрали еще год назад.
                                                          PR
                                                          commit


                                                          Да и с тех пор еще не мало изменений было.


                                                          jos_ в префиксе? тут либо была миграция причем скорее всего кривая, либо автор мега удачлив. Т.к префикс jos_ уже в 1.7 меняли, а в 2.5 был автогенератор


                                                          P.S а вот минусы вам ставят не от любви к Joomla, любой разработчик работающий с Joomla знает о ее проблемах лучше вас.

                                                            0
                                                            3.65
                                                            P.S а вот минусы вам ставят не от любви к Joomla, любой разработчик работающий с Joomla знает о ее проблемах лучше вас.

                                                            Мыши плакали, кололись, но продолжали жрать кактус?
                                                              0
                                                              3.65

                                                              То бишь о том что движок надо обновлять вы не вкурсе? но при этому у вас движок во всем виноват.


                                                              Актуальная версия Joomla! 3.8.7.
                                                              Joomla! 3.8.8 Выйдет 22 мая 2018.


                                                              Не буду перечислять все изменения, исправления, закрытие дыр со времен 3.6.5 их было не мало


                                                              А что с префиксом, миграция? как делали миграцию.


                                                              Мыши плакали, кололись, но продолжали жрать кактус?

                                                              Нет мыши просто потихоньку исправляют кактус, либо просто знают как его правильно готовить.

                                                                0

                                                                Кстати будете обновляться не забудьте воспользоваться функцие исправление БД ибо в структуре тоже были исправления

                                                                  0
                                                                  Вы бы внимательней читали, что выше написано. Я два раза, вроде, упомянул, что не было никаких миграций, всё «с нуля». Это раз
                                                                  И второе. Вы мне хотите сказать, что sql запросы — конкретно вот по этому модулю популярных статей — с версии 3.6.5 до версии 3.8.7 кардинально изменились и теперь нет тех общих проблем, что я описал?
                                                                  Нет мыши просто потихоньку исправляют кактус

                                                                  Вот я для себя и исправляю. Другим ничего не впариваю.
                                                                    0
                                                                    Вы бы внимательней читали, что выше написано. Я два раза, вроде, упомянул, что не было никаких миграций, всё «с нуля». Это раз

                                                                    В Joomla 3 префикс базы данных jos_ бывает 2-х случаях.


                                                                    1. Миграция с Joomla 1.5 (уже в 2.5 были другие префиксы, а в Joomla 3 )
                                                                    2. Прописывание его руками (мало вероятно, ибо если и пишут руками то префикс зачастую делают похожим на название сайта.)
                                                                      Совпадение? не думаю

                                                                    конкретно вот по этому модулю популярных статей — с версии 3.6.5 до версии 3.8.7 кардинально изменились

                                                                    Чтобы это понять достаточно просто перейти по ссылкам на PR и Commit которые я дал выше. Или вы код читать не умеете?


                                                                    Теперь дальше, конечно у вас проблемы с таблицей com_content есть, причин может быть много, начиная от кривой миграции, настроек сервера, до просто неудачно созданной бд, Ну и сама таблица не особо удачная для больших объемов. Однако к описанной вами проблеме это отношение не имеет, в противном случае такой разницы быть не должно.


                                                                    Если у вас такая разница при включение\отключении ACL то и причину нужно искать в нем. Если быть точнее в получении уровней доступа конкретного пользователя. А именно с получением вот этих значений a.access IN (1,1,2,3,6). Значения 1,1,2,3,6 берутся из таблицы '#__viewlevels' в данной функции Делается это единожды. Видно в отладке.


                                                                    Есть конечно дубль запроса #_usergroup но это к данному посту тоже отношения не имеет.


                                                                    Все это можно проверить посмотрев в отладку (возможно идут повторные запросы либо еще какие косяки с этим, хотя по сути это должно влиять на весь сайт) либо в ручную прописать access в запросе и посмотреть на разницу.


                                                                    Да и вообще, стоит посмотреть на сам сайт что там понаставлено и выложено, может вы вообще поставили варезный quick_start какого нибудь шаблона, где чего только не понапихано.


                                                                    Вот я для себя и исправляю.

                                                                    А могли бы для других. Joomla это OpenSorce и там всегда рады энтузиастам помогающим с оптимизацией и развитием. Ссылка на репозиторий.


                                                                    Другим ничего не впариваю.

                                                                    Ну как же не впариваюете, впариваете про то что нашли панацею. Как решить проблему с "Производительность Joomla на больших объемах контента"


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




                                                                    Кстати запрос который делает данный модуль, да и com_conent сейчас другой, да и саму базу подправляли.


                                                                    Не сказал бы что мне нравиться и этот запрос. Но это уже лучше было (сам com_contnet пользуюсь только в маленьком личном блоге в котором < 100 итемов)


                                                                    Дискутировать дальше смысла не вижу, не по причине отношения к движку, а скорее по причине того, что обсуждать не актуальную версию ядра нет ни какого смысла.


                                                                    Так что начать стоит с обновления ядра. А потом уже строчить пост на habr, а то писать и делать выводы, предлагать решения (возможно и правильные и интересные) вовлекая в дискуссию других людей, с версией ядра от 13 декабря 2016 года (~ 1,5 года назад) не очень то корректно учитывая количество обновлений и их объем.


                                                                    Кроме того. Когда проводятся любые тестирования. Указываются все сведения. А то сейчас выясним что у вас 64mb рамы, php 5.2, msql 5.1 и древний apache. Это так от балды для примера.


                                                                    P.S Я еще раз повторюсь разработчикам работающим с Joomla ничего доказывать не надо, они знают о всех проблемах не хуже вас. Да и ни кто их и не скрывает, не так много людей в данной сфере которые будут что-то защищать только из-за любви.


                                                                    Причем корень всех проблем один, ну а какой это уже совсем другая тема.

                                                                      0

                                                                      еще такой префикс бывает в некоторых квикстартах, и при установке в панельках хостеров.

                                                              +1
                                                              Совпадение? не думаю

                                                              Да, я прописал префикс jos руками, потому что:

                                                              1. Я к нему привык еще со времен, когда действительно приходилось работать с 1.5 на других сайтах
                                                              2. Абракадабра, сгенерированная истолятором джумлы, меня не устроила, так как в запросах в phpmyadmin этот префикс нужно постоянно печатать руками
                                                              3. Мои скрипты (архивация, бэкап и др.) настроены на него


                                                              Ваше право не верить. Но доказывать кому-то в интернете, что ты не верблюд, никакого желания у меня нет. Нужную компетентную консультацию в комментариях я уже получил выше. Так что удачи.

                                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                              Самое читаемое