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-а.

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

Комментарии (62)


  1. SDKiller
    30.04.2018 15:04

    … этого CMS-а

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


    1. altrus Автор
      30.04.2018 15:12

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


      1. shoorick
        30.04.2018 19:39

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


        1. altrus Автор
          30.04.2018 19:52
          +1

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


        1. zelenin
          30.04.2018 19:58

          например?


          1. Samouvazhektra
            30.04.2018 21:52

            Это фишка мореходов, из серии что корабли ходят, а не плавают
            http://www.boatsafe.com/kids/kidsquesshe.htm


        1. justhabrauser
          01.05.2018 01:35

          Это исключение. Грубо говоря для англичан корабль == лодка. Оно she.


        1. Tippy-Tip
          01.05.2018 10:56

          Традиция, сэр! Вон во французском языке слово «весна» вообще мужского рода.


      1. VolCh
        01.05.2018 16:18

        Текст на русском языке.


    1. nikitasius
      30.04.2018 15:43
      -1

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


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

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


      1. zikkuratvk
        30.04.2018 15:51
        +2

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


        1. altrus Автор
          30.04.2018 16:33

          а VIP по-вашей схеме это он или она?


          1. PastorGL
            30.04.2018 17:27

            VIP это person, а person это they с тех пор как политкорректность стала частью западной культуры.


            1. altrus Автор
              30.04.2018 18:15
              -1

              Тогда и CMS-ы — they. Из поликорректности. Как часть западной культуры.


      1. nikitasius
        30.04.2018 20:43

        :facepalm:

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


  1. zikkuratvk
    30.04.2018 15:29
    +1

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


    1. altrus Автор
      30.04.2018 15:42
      -1

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

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

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


      1. sumanai
        30.04.2018 15:46
        +1

        А что может быть не так с базой? )))

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


      1. zikkuratvk
        30.04.2018 15:55
        +2

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


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


        1. altrus Автор
          30.04.2018 16:22
          -1

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


      1. Dmitri-D
        30.04.2018 16:10
        +1

        А что может быть не так с базой?

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


        1. altrus Автор
          30.04.2018 16:20
          -1

          Спасибо, проверю.


        1. altrus Автор
          30.04.2018 18:13
          -1

          Вы правы, это был индекс. Но как-то странно.

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

          В среднем, запрос c ACL был процентов на 50% по времени тяжелей с рабочими индексами, чем без ACL. Но что опять произошло с индексами через небольшое время после перестройки и почему?


          1. bgBrother
            30.04.2018 21:37

            Не уверен в своём высказывании, прошу сразу простить, но может у вас индексы в отведенную БД память не влазят? Смотрели конфигурацию?


            1. altrus Автор
              01.05.2018 06:16

              Всё на хостинге. Качеством и техническим уровнем сервиса пока был доволен.


          1. Dmitri-D
            01.05.2018 02:09

            Возможно это не ваш случай, но _обычно_ индексы получаются перекошенные, если идут вместе подряд DDL и DML запросы. Т.е. менять схему на лету с данными.
            Или вот — тоже простой способ выстрелить себе в ногу — это удалить все старые данные таблицы и быстренько наполнить другие данные, для которых старая статистика работать не будет. Например были все записи с одним и тем же значением в проиндексированном поле — такой индекс игнорируется по статистике, а потом вы наполняете новыми, где эта колонка содержит или уникальные или почти уникальные данные — если индекс по-прежнему игнорируется (статистика велит), то всё, запросы будут тормозить.
            База данных — штука не глупая, обычно она сам обновляет статистику, но иногда почему-то не обвновляет, или забывает обновить


            1. altrus Автор
              01.05.2018 06:49

              Давайте конкретно мой тестируемый случай рассматривать. Вчера были запросы большие, я сделал optimize на _content и _categories. Время запросов стало маленьким на 3 минуты, и затем опять большим. Снова optimize, снова маленькое и уже надолго. Утром сегодня проверяю — опять большое (300мс-1200мс). Причем, за ночь в _content ничего не добавлялось.

              Из того, что я делал с БД раньше (давно) — чистка _assets вот этим способом и удалял руками из _content данные.


  1. fspare
    01.05.2018 00:41

    Глупый вопрос, но нельзя ли для ACL воткнуть кэширование? По идее это такие вещи, которые не так часто меняются и отлично подпадают под возможность кэширования(я про ACL). Механизмов хватает — Redis/Memcache/(да даже тупое кэширование файловое) должно улучшить на порядки производительность. Конечно, это приведет к модификации исходного кода Joomla(что не хорошо в плане последующих апгрейдов)… Но даже не знаю стоит ли из бетонных блоков пытаться слепить детский песочный домик или слегка допилить напильником то, что уже есть…


  1. Kwisatz
    01.05.2018 02:55

    Чисто из академического интереса: покажите пожалуйста explain длинного запроса.


    1. altrus Автор
      01.05.2018 06:09

      image
      Время опять стало большим (1100мс)


      1. Dmitri-D
        01.05.2018 06:26

        скорее всего — using temporary и using filesort — вот что тормозит
        Плюс к этому вопрос — почему ключ такой длинный? Что там такое в ключе аж на 203 байт?
        Похоже индекс не влазит в память и был вытеснен. Вам нужно увеличить память для кеширования или поменять диск на более быстрый


        1. altrus Автор
          01.05.2018 06:48

          То есть во время выполнения этого запроса на большой таблице при создании temporary table слетают индексы у _content, правильно я понимаю?


          1. Kwisatz
            01.05.2018 20:47

            Во время выполнения этого запроса сервер получает 201 тысячу строк от storage engine частично без использования индексов а затем все это весело размешивает, используя дисковую сортировку.


          1. Dmitri-D
            02.05.2018 04:18

            в таблице большой ключ cat_idx — 203 байта на каждую запись. Что в этом ключе? Из-за того что он большой, а памяти выдено мало — данные сортируются во временном файле. Поэтому и тормоза.

            Что касается быстрых и медленных периодов — сравните query plan когда быстро и когда медленно.


            1. Kwisatz
              02.05.2018 04:34

              Я думаю по сравнению с остальными проблемами это слезы.


      1. Dmitri-D
        01.05.2018 06:31

        и sort buffer тоже увеличить


        1. altrus Автор
          01.05.2018 06:44

          База на хостинге, я ничего не могу. Hostland.


      1. Kwisatz
        01.05.2018 12:33

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

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


        1. altrus Автор
          01.05.2018 13:25

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

          5. Вопрос: это из-за shared хостинга такое? Недерминированное выделение памяти под сортировку и временную таблицу?


          1. Kwisatz
            01.05.2018 13:58

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

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

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


            1. sumanai
              01.05.2018 14:46

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

              Вангую что никак.


              1. altrus Автор
                01.05.2018 15:17

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


            1. altrus Автор
              01.05.2018 15:08

              Запросы стали опять долгие. Ваш — быстрый.

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

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

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


              1. Kwisatz
                01.05.2018 20:24

                Смотрите, конкретно этот запрос сам по себе сейчас не важен.

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

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

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

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

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

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

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

                На вскидку, самое простое: добавить индекс по времени и поставить условие по нему первым (или в подзапрос вынести), это уже облегчит жизнь небольшим сайтам. Убрать кейс из условия к чертям, он там не нужен абсолютно. Ну и ACL должен работать по маскам или хешу но не через in, но при малом количестве данных по идее уже не будет играть столь серьезную роль.


                1. altrus Автор
                  02.05.2018 15:33

                  Этот модуль делает следующее — показывает 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


                  1. Kwisatz
                    02.05.2018 20:14

                    Я догадался уже)
                    Конечно есть, индекса по датам то нет как минимум. У нормального запроса должны быть указано using index. А у вас скорее всего using where,using filesort.

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

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

                    И его можно очень сильно облегчить если грамотно организовать подзапрос. Даже без оптимизаций.
                    Какая универсальность в том же left outer join к таблице content я честно не догадываюсь.
                    А приколы вроде case которое спокойно разворачивается в нормальное условия практически разрывают оптимизатор пополам.


                  1. Kwisatz
                    02.05.2018 20:18
                    +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.


                    1. altrus Автор
                      03.05.2018 05:00

                      Да, правильно. Когда долгие запросы. у меня «Using temporary; Using filesort». Когда быстрые, «Using where; Using filesort», но это тоже не правильно, как я понимаю.

                      Будет время я все-таки замеряю разницу в скорости стандартного решения и оптимизированного под конкретные запросы. Хотя не понятно, как запись в temporary table оценивать — оно то есть, то нет на одном запросе и с одними данными. А влияние оказывает критическое.


          1. Kwisatz
            01.05.2018 20:33

            Попробуйте кстати explain extended


        1. altrus Автор
          01.05.2018 13:44

          Хостер ответил, что sort_buffer_size = 4194304 байт (4 Мб).


      1. Kwisatz
        01.05.2018 13:06

        Попробуйте этот запросик

        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


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


      1. VolCh
        01.05.2018 16:16

        Возможно, оптимизатор какое-то время собирает статистику, а потом решает, что filesort и temporary быстрее будет. Сравните explain сразу после optimize и когда опять начнёт тормозить.


  1. al707
    01.05.2018 06:09

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


    1. altrus Автор
      01.05.2018 06:14

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


  1. konservs
    01.05.2018 08:46

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


    1. zikkuratvk
      01.05.2018 15:43

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


      1. altrus Автор
        01.05.2018 15:48

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


        1. zikkuratvk
          01.05.2018 16:43

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


          1. altrus Автор
            01.05.2018 18:21

            Joomla сильно тормозит на большом количестве статей — это известный факт, поднимался на форумах не раз.
            Торможения из-за не эффективных запросов и ACL — это тоже факт.
            Статья моя об этом. Если у вас все хорошо — значит эта проблема вас не касается.


            1. altrus Автор
              03.05.2018 05:02

              Извиняюсь.
              Что-то я не заметил, что разговор про статью konservs.com/post/179. и все перепутал


      1. konservs
        02.05.2018 20:42

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


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


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


        1. zikkuratvk
          02.05.2018 21:02

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