Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

ocStore тормозит при выключенном подсчете товаров


markimax

Recommended Posts

Во-первых это несколько отдаляет от чистого OC.

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

Как по мне, кеширование - самое оно.

Тригерами MySql

Надіслати
Поділитися на інших сайтах


А если удалить запросы, чтобы вообще не подсчитывалось количество товара, и выводить все товары на одну страницу используя лэйзилоад(убрать пагинацию совсем)?

Бесконечная страница при 10к товаров...да пользователи нах пошлют)

Надіслати
Поділитися на інших сайтах


А если создать доп таблицу, в которой и хранить все счётчики?

На все случаи таблиц (полей) не насоздашь, попытаться можно.

Получить md5 запроса и сохранить.

 

 

Как по мне, кеширование - самое оно.

Кеширование  - это как вариант, но бывают (часто) медленные файловые хостинги, это если использовать файловый кеш.

 

 

Тригерами MySql

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

 

Бесконечная страница при 10к товаров...да пользователи нах пошлют)

 

Кто-то листает 10К? Как показывает опыт - макс. 5

Надіслати
Поділитися на інших сайтах

На все случаи таблиц (полей) не насоздашь, попытаться можно.

Получить md5 запроса и сохранить.

 

зачем поля.

создаем таблицу типо 

CREATE TABLE `count_prod` (
`id` int(11) NOT NULL auto_increment,
`count` int(11) NOT NULL DEFAULT 0,
`category_id` int(11) NOT NULL DEFAULT 0,
PRIMARY  KEY (`id`)
) TYPE=MyISAM;

Далее тригер:

TRIGGER oc.`tr_product_insert`
AFTER INSERT
ON oc.product
FOR EACH ROW
BEGIN
update count_prod
  set count = count+1    
where category_id = NEW.category_id;
END

Функция

public function getCountProd($catid) {
$sql='select cp.count from count_prod cp
where cp.category_id=(int)$catid';
return $query($sql)
}

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

Тригер на создание новой категории и удаление. Тригер на продукт и его удаление.

Ну эт на простой пример, в ос сторе надо учесть неск параметров, но тригер написать можно

Выгодно будет, даже если овер много категорий, чем подсчёт 10к, хотя как знать конечно)

Надіслати
Поділитися на інших сайтах


Поидее для поиска можно и старый метод оставить.

Статус  тригером можно проверить, тогда будет три тригера на вставку, изменение и удаление товара. А вот с датой конечно не знаю, проверить её можно, но как проверить достигла дата нужного числа или нет хз. Может есть какоето решение?)

Надіслати
Поділитися на інших сайтах


сегодня не достигла, завтра достигла. как бы там ни было все эти костыли годятся для частных решений под конкретную базу, но никак не в релиз ocStore

Надіслати
Поділитися на інших сайтах

сегодня не достигла, завтра достигла. как бы там ни было все эти костыли годятся для частных решений под конкретную базу, но никак не в релиз ocStore

В принципе я фикс уже почти написал хуками. Считает только для пагинации, осталось только окно ввести в ocStore для пагинации (LIMIT в запрос и через jquery убирать с пагинации "последнюю страницу)), чтобы перебирались не все ряды товаров в категории (вдруг их там более 1000), а только дозволенные окном

Вообще не мешало бы в ocStore ввести подключение хуков и систему хуков, как я реализовал в своем модуле

Надіслати
Поділитися на інших сайтах

И так же будет на странице категорий все страницы пагинации видны?

а понял о чём)тоесть будет типо многоточия, при нажатии по которому снова будет перерасчёт?

Надіслати
Поділитися на інших сайтах


И так же будет на странице категорий все страницы пагинации видны?

а понял о чём)тоесть будет типо многоточия, при нажатии по которому снова будет перерасчёт?

Да - только "последней" не будет

Надіслати
Поділитися на інших сайтах

Клёва, ну а если дизайн резиновый, и окно под пагинацию будет вмещать по разному, будет ли какойто перерасчёт количества кнопок, или просто кнопки больше будут?

Надіслати
Поділитися на інших сайтах


ocTeam ;) А не хотите ввести сиcтему хуков в ocStore на базе __call

Чтобы было все стандартизовано. В папку залили хук и он следит за методами моделей, библиотек, переопределения контроллеров и т.п.

Надіслати
Поділитися на інших сайтах

Я еще переварю что здесь написано, после моего ответа

 

но... Вопрос есть

Что быстрее  inner join или left join?

 

так вот

вернемся к запросу

SELECT COUNT(DISTINCT p.product_id) AS total FROM t_product p
LEFT JOIN t_product_to_store p2s ON (p.product_id = p2s.product_id) 

Логичнее его переделать на

SELECT COUNT(DISTINCT p.product_id) AS total FROM t_product p 
inner JOIN t_product_to_store p2s ON (p.product_id = p2s.product_id) 

или

SELECT COUNT(DISTINCT p.product_id) AS total 
FROM t_product p, t_product_to_store p2s
where p.product_id = p2s.product_id 

зы. Может быть я как мужчина-музыкант чего-то не понимаю

Надіслати
Поділитися на інших сайтах

В запросе тормозит именно COUNT при использовании LEFT JOIN. И как уже писали раньше - потому что он обходит все строки.

Удивлён, что этот вопрос подняли только-только, ведь тем с этой проблемой на форуме было много.

 

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

Предлагаемые варианты решений были: добавить индексы или не считать вовсе, а хранить где-то отдельно эти значения.

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

Надіслати
Поділитися на інших сайтах

По вебвизору могу сказать, что пагинацией вообще мало кто пользуется, особенно если выводить на страницу не 10, а 20-25 товаров, тут будет все как в гугле - покупателю часто лень идти на следующую страницу, так что ИМХО можно ее не считать, и делать как предлагает markimax, без последней страницы. Выигрыш по скорости будет сильно больше, чем проигрыш по удобству.

  • +1 1
Надіслати
Поділитися на інших сайтах

тогда можно выбирать товары (page-1)*limit, limit+1,

- если кол-во больше limit, показывать ссылку на следующую

- если page>1 ссылку на предыдущую

- если кол-во товаров=0 и page>0, вероятно пользователь самостоятельно указал страницу, редиректить на первую

Надіслати
Поділитися на інших сайтах

По вебвизору могу сказать, что пагинацией вообще мало кто пользуется, особенно если выводить на страницу не 10, а 20-25 товаров, тут будет все как в гугле - покупателю часто лень идти на следующую страницу, так что ИМХО можно ее не считать, и делать как предлагает markimax, без последней страницы. Выигрыш по скорости будет сильно больше, чем проигрыш по удобству.

Да, однозначно. Причем так делают все и google и все нагруженные проекты, к этому значит уже привыкли, а если привыкли и "знают" - значит так и надо сделать

Надіслати
Поділитися на інших сайтах

Вопрос поднят, но не обсужден :(

Ну для себя решили - при  достаточно известно большом количестве товаров не использовать пагинацию

		$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

по крайней мере можно и нужно переписать

if (!empty($data['filter_name']) || !empty($data['filter_tag'])) {
    $sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) 
INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";
} else {
    $sql .= " INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

}

Аналогично сделать и в getProducts

 

Не нужен в выборке товар, который не привязан к магазину

Змінено користувачем chukcha
  • +1 1
Надіслати
Поділитися на інших сайтах

Вопрос поднят, но не обсужден :(

Ну для себя решили - при  достаточно известно большом количестве товаров не использовать пагинацию

		$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

по крайней мере можно и нужно переписать

if (!empty($data['filter_name']) || !empty($data['filter_tag'])) {
    $sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) 
INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";
} else {
    $sql .= " INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

}

Аналогично сделать и в getProducts

 

Не нужен в выборке товар, который не привязан к магазину

Здравствуйте. Мне тоже интересна эта тема. Сделал как вы написали выше. Но при переходе на сайт, не идет загрузка каталога, только белый экран. В журнале ошибок следующее:

 

2014-01-21 8:53:10 - PHP Notice:  Error: Unknown column 'pd.language_id' in 'where clause'<br />Error No: 1054<br />SELECT COUNT(DISTINCT p.product_id) AS total FROM product p INNER JOIN product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= '2014-01-21 08:53:00' AND p2s.store_id = '0' in /var/www/voptCj/vopt.com.ua/system/database/mysql.php on line 50
2014-01-21 8:53:12 - PHP Notice:  Error: Unknown column 'pd.language_id' in 'where clause'<br />Error No: 1054<br />SELECT COUNT(DISTINCT p.product_id) AS total FROM product p INNER JOIN product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= '2014-01-21 08:53:00' AND p2s.store_id = '0' in /var/www/voptCj/vopt.com.ua/system/database/mysql.php on line 50
Надіслати
Поділитися на інших сайтах


ну да... ошибочка, вообще-то я писал только для примера, но не для исполнения.

$sql .= " INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

Вот правильный. Надеюсь, что бекап файлов вы сделали предварительно?

  • +1 1
Надіслати
Поділитися на інших сайтах

ну да... ошибочка, вообще-то я писал только для примера, но не для исполнения.

$sql .= " INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

Вот правильный. Надеюсь, что бекап файлов вы сделали предварительно?

Спасибо.

Надіслати
Поділитися на інших сайтах


Продолжим?

public function getProductRelated($product_id) {
...
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_related pr INNER JOIN " . DB_PREFIX . "product p ON (pr.related_id = p.product_id) INNER JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pr.product_id = '" . (int)$product_id . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");

На малом количестве посетителей это не существенно

 

Кстати, везде, где используется таблица  DB_PREFIX . "product_to_store " нужно использовать INNER JOIN

Надіслати
Поділитися на інших сайтах

  • 2 weeks later...

Ну для 1 магазина и 1 языка вопрос решается просто (к тому же я не использую дату доступности товара) 1.5.5.1.1

 

заменить:

$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= '" . $this->NOW . "' AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";

на

 
$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' ";

Тормоза пропали, дофига категорий ~ 5000 товаров. Генерация главной (с включенной стенкой категорий)

Total time 0.8332 seconds

Надіслати
Поділитися на інших сайтах


 

Тормоза пропали, дофига категорий ~ 5000 товаров. Генерация главной (с включенной стенкой категорий)

Total time 0.8332 seconds

 

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

 

Я тут подумал, если бы предусмотреть изменение таких запросов всем скопом через админку, это круто облегчило бы жизнь пользователю (но увы, я не представляю, как так на лету изменять модель). То есть может в виде модуля, чтобы были элементарные чекбоксы с тем, ЧТО стоит учитывать в запросах. Если магазин 100% будет одноязычным и одновалютным, то чтобы юзер просто снял галочку с чекбоксов мультиязычности и мультивалютности, и все запросы сразу перестали бы ее учитывать.

Змінено користувачем RGB
Надіслати
Поділитися на інших сайтах

Створіть аккаунт або увійдіть для коментування

Ви повинні бути користувачем, щоб залишити коментар

Створити обліковий запис

Зареєструйтеся для отримання облікового запису. Це просто!

Зареєструвати аккаунт

Вхід

Уже зареєстровані? Увійдіть тут.

Вхід зараз
×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.