Ответвление SimplaCMS

Привет всем! Давненько не был... смотрю 1.22 появился уже и занулили. Друзья, Поделитесь кому не жалко нулом рабочим. Что бы в очередной раз самому одно и тоже не проделывать с оригиналом. ;) Спасибо большое и респект за!
 
Люди, кто шарит в mysql.

В ходе багтрахинга на окее 1.2.2 выяснилась причина долгой загрузки главной страницы. Оказалось, что
get_new_products функция, которая работает через фукнцию get_products
выполняется медленно на нашей большой базе, а причина замедления вот этот запрос.

Код:
SELECT DISTINCT p.id, p.url, p.brand_id, p.position, p.created AS created, p.visible, p.featured, p.rating, p.votes, p.last_modify, l.name, l.meta_title, l.meta_keywords, l.meta_description, l.annotation, l.body, l.special
FROM s_products p
LEFT JOIN s_lang_products l ON l.product_id = p.id
AND l.lang_id =1
WHERE 1
AND (

SELECT count( * ) >0
FROM s_variants pv
WHERE pv.product_id = p.id
AND (
pv.stock IS NULL
OR pv.stock >0
)
LIMIT 1
) =1
AND p.visible =1
ORDER BY p.created DESC
LIMIT 0 , 4

Работа запроса на базе 60к товаров, выполняется примерно 2 секунды. Причем, если из запроса убрать LEFT JOIN s_lang_products, все нормально работает.

Код:
SELECT DISTINCT p.id, p.url, p.brand_id, p.position, p.created AS created, p.visible, p.featured, p.rating, p.votes, p.last_modify
FROM s_products p

WHERE 1
AND (

SELECT count( * ) >0
FROM s_variants pv
WHERE pv.product_id = p.id
AND (
pv.stock IS NULL
OR pv.stock >0
)
LIMIT 1
) =1
AND p.visible =1
ORDER BY p.created DESC
LIMIT 0 , 4

Такой запрос выполняется 0.0007 секунд!

Вот EXPLAIN от злополучного запроса.
112I1.png


112I1
 
удалось решить проблему следующим образом. в классе products api/products.php

меняем запрос в базу в методе get_products
на следующий

Код:
"SELECT
                p.*,
                $lang_sql->fields
                FROM (SELECT DISTINCT
                p.id,
                p.url,
                p.brand_id,
                p.position,
                p.created as created,
                p.visible,
                p.featured,
                p.rating,
                p.votes,
                p.last_modify
               
            FROM __products p
           
            $category_id_filter
            $variant_join
            $currency_join
            $yandex_filter
            WHERE
                1
                $product_id_filter
                $brand_id_filter
                $features_filter
                $keyword_filter
                $is_featured_filter
                $discounted_filter
                $in_stock_filter
                $visible_filter
                $price_filter
                $group_by
            ORDER BY $order
            $sql_limit) p
            $lang_sql->join
        "
 
babahalki уже выкладывал нулл 1.2.2 пару страниц назад

какие операции не связанные с обнулением этого нула с ним ещё проделаны? в сравни с оригиналом.
просто шас поставил, сразу вот что то картинок не видно товара и пр. так, что бы знать что там убрано... спасибо.
 
какие операции не связанные с обнулением этого нула с ним ещё проделаны? в сравни с оригиналом.
просто шас поставил, сразу вот что то картинок не видно товара и пр. так, что бы знать что там убрано... спасибо.
Я там писал про изменения. Из важного ничего не менялось, картинки порезаны. С тех пор приличное кол-во изменений внесли, в пору выкладывать собственный апдейт.

Косяки текущей версии okay CMS:
1.Выгрузка яндекс директ YML не работает на большой базе (недостаточно памяти). Решено.
2. Интеграция мультиязычной поддержки привела к серьезному замедлению системы на больших базах (2.5 сек для главной страницы - перебор) - решено
3. Включенный imagick вместо GD дает заметное невооруженным глазом снижение качества картинок - решено.
4. Добавлена функция автоматической генерации мета тегов не только для товаров, но и для разделов сайта.
5. Добавлен новый порядок сортировки товаров на сайте: random и сортировка по популярности (кол-во просмотров карточек товаров), теперь у нас по-умолчанию используется именно этот способ.
6. По нашей просьбе разрабы сделали нам еще вот что. обычная симпла в шаблоне для категории products.tpl давала переменную $brand, если из категории выбран еще какой-то бренд. В окее такую возможность порезали, мы попросили и нам вернули. Очень нужно для СЕО.
7. Увеличили кол-во отображаемых товаров в админке, теперь посмотреть можно 200, 300, 400 и 500 товаров.
8. Значительно расширен генератор sitemap.
9. Одно из самых важный изменений!!! Если кто знает, и Симпла, и ее незаконнорожденный ОКЕЙ имели такой жестокий недостаток. Если в админке в разделе Свойства товаров ты хочешь отключить фильтр какого-то параметра не во всех разделах, а только в определенных, это можно сделать, ткнув на нужный параметр и выбирая галочками категории. Всегда думали, что отключение приводит к исчезновению соответствующего фильтра на сайте, а включение возвращает все назад. Оказалось, что система ведет себя иначе. В случае отключения галочки какой-то категории в настройках свойства товара, система не только выключает его, но и удаляет значения этого свойства у всех товаров этой категории. Вы отключили, например, длину, а система взяла и убила все параметры длины у товаров в этой группе! Разрабы окея в ответ на вопрос об этом, сказали, что это не баг, а фича. :)
Мы отключили эту "фичу" у себя. Чтобы удалить какие-то свойства у товаров, надо удалить само свойство, а не просто снять галочку.

Люди, кто шарит в mysql.

В ходе багтрахинга на окее 1.2.2 выяснилась причина долгой загрузки главной страницы. Оказалось, что
get_new_products функция, которая работает через фукнцию get_products
выполняется медленно на нашей большой базе, а причина замедления вот этот запрос.

Код:
SELECT DISTINCT p.id, p.url, p.brand_id, p.position, p.created AS created, p.visible, p.featured, p.rating, p.votes, p.last_modify, l.name, l.meta_title, l.meta_keywords, l.meta_description, l.annotation, l.body, l.special
FROM s_products p
LEFT JOIN s_lang_products l ON l.product_id = p.id
AND l.lang_id =1
WHERE 1
AND (

SELECT count( * ) >0
FROM s_variants pv
WHERE pv.product_id = p.id
AND (
pv.stock IS NULL
OR pv.stock >0
)
LIMIT 1
) =1
AND p.visible =1
ORDER BY p.created DESC
LIMIT 0 , 4

Работа запроса на базе 60к товаров, выполняется примерно 2 секунды. Причем, если из запроса убрать LEFT JOIN s_lang_products, все нормально работает.

Код:
SELECT DISTINCT p.id, p.url, p.brand_id, p.position, p.created AS created, p.visible, p.featured, p.rating, p.votes, p.last_modify
FROM s_products p

WHERE 1
AND (

SELECT count( * ) >0
FROM s_variants pv
WHERE pv.product_id = p.id
AND (
pv.stock IS NULL
OR pv.stock >0
)
LIMIT 1
) =1
AND p.visible =1
ORDER BY p.created DESC
LIMIT 0 , 4

Такой запрос выполняется 0.0007 секунд!

Вот EXPLAIN от злополучного запроса.
112I1.png


112I1

Блин, возникла проблема с поиском. Дело в том, что поиск хочет искать в поле l.name, которой на момент вывода перечня товаров еще нет, если переставить поиск после этой таблицы, то он будет искать, но только в ограниченной limit выдаче.

Засада.
Так поиск работает, но выдает кучу страниц, где на каждой странице всего по 1 или 2 товара.
Код:
"SELECT
                p.*,
                $lang_sql->fields
                FROM (SELECT DISTINCT
                p.id,
                p.url,
                p.brand_id,
                p.position,
                p.created as created,
                p.visible,
                p.featured,
                p.rating,
                p.votes,
                p.last_modify
     
            FROM __products p
 
            $category_id_filter
            $variant_join
            $currency_join
            $yandex_filter
            WHERE
                1
                $product_id_filter
                $brand_id_filter
                $features_filter
                $is_featured_filter
                $discounted_filter
                $in_stock_filter
                $visible_filter
                $price_filter
                $group_by
            ORDER BY $order
            $sql_limit) p
            $lang_sql->join
            WHERE 1
            $keyword_filter
        "

Еще вариант не искать в языковой таблице совсем, но тогда зачем он вообще нужен этот язык?

Придумал 3 вариант. Вернуть концепцию запроса, если осуществляется поиск по сайту.

Остановились на 3 варианте. Для поиска используется стандартная конструкция. Сначала join таблицы товаров с языками, потом поиск по базе и выдача с установленным лимитом. Поиск работает, конечно, дольше, но зато функциональность никак не пострадала, а скорость работы даже выросла.
На наших 56 тыс. товаров все это заметно невооруженным глазом. Главная страница, пагинация по разделам, все работает быстрее.
Вот что нужно поменять:
кусок кода в get_products,
начиная с
Код:
$query = ............
заканчивая,
Код:
"
;
меняем на
Код:
    if(!empty($filter['keyword']) || !empty($filter['keyword'])) {
       $query = "SELECT DISTINCT
         p.id,
         p.url,
         p.brand_id,
         p.position,
         p.created as created,
         p.visible,
         p.featured,
         p.rating,
         p.votes,
         p.last_modify,
         $lang_sql->fields
       FROM __products p
       $lang_sql->join
       $category_id_filter
       $variant_join
       $currency_join
       $yandex_filter
       WHERE
         1
         $product_id_filter
         $brand_id_filter
         $features_filter
         $keyword_filter
         $is_featured_filter
         $discounted_filter
         $in_stock_filter
         $visible_filter
         $price_filter
         $group_by
       ORDER BY $order
       $sql_limit
       ";
     } else {
       $query = "SELECT
         p.*,
         $lang_sql->fields
         FROM (SELECT DISTINCT
         p.id,
         p.url,
         p.brand_id,
         p.position,
         p.created as created,
         p.visible,
         p.featured,
         p.rating,
         p.votes,
         p.last_modify
       FROM __products p
       $category_id_filter
       $variant_join
       $currency_join
       $yandex_filter
       WHERE
         1
         $product_id_filter
         $brand_id_filter
         $features_filter
         $is_featured_filter
         $discounted_filter
         $in_stock_filter
         $visible_filter
         $price_filter
         $group_by
       ORDER BY $order
       $sql_limit) p
       $lang_sql->join
       WHERE 1
       $keyword_filter
       ";
     }

Вылез еще 1 интересный баг. Я так и не смог понять в чем дело.
После манипуляции с этим запрос везде все складно, кроме корзины. Сама корзина работает, но вот при добавлении туда товара в информере сверху изменений не происходит.
Вот до чего я доковырялся.
api/cart.php метод get_cart()
использует метод get_products(), который мы изменили. используется get_products вот как:
Код:
//объявляем переменную в виде массива.
  $products = array();
//циклом для каждой строки stdObject, который у нас получается
//путем fetch_object в методе db->results(), который вызывается
//get_products, мы добавляем это в наш $products с элементами
//в виде id товара p->id
  foreach($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) {
  $products[$p->id]=$p;

//имеем на выходе $products со всеми товарами в корзине, какими именно написано в
//$products_ids, который берет это в $_SESSION['shopping_cart']

Если бы что-то не работало, то информер не показывал бы товаров в корзине вообще, а он показывает их при обновлении страницы, не показывает после клика на кнопку купить.

Сделал родной запрос $query не только для поиска, но и для случаев, когда указываются id (корзина).
Теперь информер работает.
Но в чем была причина такого поведения???
Очевидно, что данные о том, что товар добавлен отправляются, но ajax корзина не обновляет информер. Почему?
Кто нибудь может мне ответить?
 
Последнее редактирование модератором:
не думал что спрошу когдато), но

как правильно делать перенос ?
(с хостинга и домена -> на хостинг и домен)

дамп базы со старого залил на новый.
файлы все скопировал и залил
compiled подчистил все
в config.php подправил пороль логин

запускаю - итог - > белый экран

вопрос - что ещё сделать ?

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

как правильно делать перенос ?
(с хостинга и домена -> на хостинг и домен)

дамп базы со старого залил на новый.
файлы все скопировал и залил
compiled подчистил все
в config.php подправил пороль логин

запускаю - итог - > белый экран

вопрос - что ещё сделать ?
В config.php ещё и название БД может отличаться.
Выведи ошибки и посмотри что пишет.
 
как в симпле реализовать "скачать прайс лист" в меню что бы по нему ткнул и прайс начал качаться с хостинга где цмс установлена ?

Можно прикрутить стандартный экспорт в csv, но он работает долговато. Лучше просто вывести на сайт ссылку на yandex.xml. Прайс будет в формате YML. Если нужно именно CSV, можно добавить в симплу плугин, который будет выполнять определенный запрос на выборку нужного. Я такой запрос делал, он довольно быстро собирает название, артикул, цену, остатки + параметры товаров.

Вчера реализовали у себя мощную автоматизацию. Обновление остатков и цен по YML поставщика. Теперь 4 раза в сутки система скачивает YML поставщика, парсит этот файл, а полученную таблицу потом загоняет в базу. Поиском по бренд + артикул производителя ищет совпадения в нашей базе обновляет остатки и цены и вадает лог, сколько товаров из YML нашлось, а сколько нет.



Для держателей больших баз. Наверняка вы уже успели заметить как симпла или окей долго открывает разделы, в которых много товаров. Все дело в том, что система при загрузке раздела выполняет get_options и получает список значений для фильтров, чтобы их отобразить. В нашей случае в таблице s_options, в которой хранятся все свойства товаров 7.5млн. записей. Конечно, выборка из такой таблица требует времени, у нас полная загрузка некоторых разделов длилась до 15 секунд. А ведь нам совсем не нужны свойства всех товаров при открытии разделов, нам нужны только свойства у товаров из выбранной категории. Такой таблицы в симпле нет, поэтому придется ее создать.

Код:
create table t_categories_options
engine = MyIsam

select pc.category_id, o.*
from s_options o
left join
s_products_categories pc
on o.product_id = pc.product_id
group by pc.category_id, o.feature_id, o.value;

alter table t_categories_options
ADD INDEX (category_id),
ADD INDEX (feature_id),
ADD INDEX (lang_id);

Таблица создана и в ней уже не 7.5млн. записей, а всего 850тыс., т.е. мы облегчили таблицу почти в 10 раз, без потери нужной функциональности.

На основе имеющего в системе метода get_options добавляем новый метод в /api/features.php

Код:
    public function get_categories_options($filter = array()) {
        $feature_id_filter = '';
        $product_id_filter = '';
        $category_id_filter = '';
        $visible_filter = '';
        $brand_id_filter = '';
        $features_filter = '';
   
        if(empty($filter['feature_id']) && empty($filter['product_id'])) {
            return array();
        }
   
        $group_by = '';
        if(isset($filter['feature_id'])) {
            $group_by = 'GROUP BY feature_id, value';
        }
   
        if(isset($filter['feature_id'])) {
            $feature_id_filter = $this->db->placehold('AND po.feature_id in(?@)', (array)$filter['feature_id']);
        }
   
        if(isset($filter['category_id'])) {
            $category_id_filter = $this->db->placehold('AND po.category_id in(?@)', (array)$filter['category_id']);
        }
   
        if(isset($filter['visible'])) {
           $visible_filter = $this->db->placehold('INNER JOIN __products p ON p.id=po.product_id AND visible=?', intval($filter['visible']));
        }
   
        if(isset($filter['brand_id'])) {
            $brand_id_filter = $this->db->placehold('AND po.product_id in(SELECT id FROM __products WHERE brand_id in(?@))', (array)$filter['brand_id']);
        }

   
        $lang_id  = $this->lang->lang_id();
        $lang_id_filter = '';
        if($lang_id) {
            $lang_id_filter = $this->db->placehold("AND po.lang_id=?", $lang_id);
        }
   
        $query = $this->db->placehold("SELECT
                po.category_id,
                po.product_id,
                po.feature_id,
                po.value,
                po.translit,
                count(po.product_id) as count
            FROM t_categories_options po
            $visible_filter
       
            WHERE
                1
                $category_id_filter
                $lang_id_filter
                $feature_id_filter
                $brand_id_filter
            GROUP BY po.feature_id, po.value
            ORDER BY po.value=0, -po.value DESC, po.value
        ");
   
        $this->db->query($query);
        return $this->db->results();
    }

Что мы тут сделали.
1. В нашей таблице сразу есть category_id, поэтому упрощаем фильтр по категориям.
2. Удаляем лишнее.
3. В запросе меняем место исправленного фильтра и название таблицы.


Теперь заставим симплу использовать новый метод при загрузке раздела.
Идем в /view/productsView.php
Меняем 2 места:
1.
Код:
$options = $this->features->get_options($options_filter);
на:
Код:
$options = $this->features->get_categories_options($options_filter);
2.
Код:
foreach ($this->features->get_options(array('feature_id' => $feature->id)) as $fo) {
на:
Код:
foreach ($this->features->get_categories_options(array('feature_id' => $feature->id)) as $fo) {
Скорость загрузки самых тяжелых разделов сократилась до 3 сек.
Надеюсь, можно будет еще ускорить. Жду предложения и замечания.
 
Последнее редактирование модератором:
Назад
Сверху