Здравствуйте. Запустил memcached. Настроил профайлер запрос в БД. Добавляю кэширование запросам на странице категорий и товаров. Возник вопрос как кэшировать запросы, которые находятся в файле index.php ? opencart 1.5.6 Использую встроенные функции кэширование с работой memcached $this->cache->get($key_cache); $this->cache->set($key_cache, $query, false, 7200); // Хранить результат 2 часа Например: // Settings $query = $db->query("SELECT * FROM " . DB_PREFIX . "setting WHERE store_id = '0' OR store_id = '" . (int)$config->get('config_store_id') . "' ORDER BY store_id ASC"); Заранее благодарен.
Зачем? Кешировать имеет смысл тяжёлые запросы связанные с контентом, а не лёгкие связанные с работой самого движка. В MySQL ведь тоже есть кеширование и запросы из index.php в виду своей частоты и статичности должны попадат в тот кеш. Но если сильно хотите кешировать, надо просто перенести инициализацию кеша выше инициализации базы, а дальше вызывать как обычно, но без $this.
Решил даже не обращаться к БД по таким запросам, т.к. они не меняются, а вызываются на каждой странице. Судя по графику нагрузки в часы пик начинает подседать MySQL. Решил как можно больше снять с нее работы. Не кэшировал запросы, где выбираются цены и остатки товара, для поддержания актуальности данных. А категории, меню, настройки и т.д. отправил в memcached Поправьте меня, пожалуйста, если я перегибаю палку. В файле index.php сделал как вы подсказали. Запрос благополучно ушел в кэш.
А зачем вы отдельно sql для ключа захешировали, а потом заново его в сам запрос вписали? Надо загнать sql в переменную и потом использовать её в обоих местах. Во-первых, дублирование кода - это плохо, а во-вторых, если вы в будущем хотя бы один символ измените в этом sql (в любом из двух), ключ перестанет соответствовать самому запросу. А среди запросов с ценами есть и одни из самых нагруженных в ОК и их имеет смысл кешировать в первую очередь! У вас же цены не меняются каждые два часа? А после выгрузки из 1С или ещё какого-то обновления данных, можно просто вручную сбросить кеш.
На самом деле ключ уникализируется за счет (int)$config->get('config_store_id') А все остальное считай "солью" Но я бы сравнил время доступа к данным при чтении из базы и из кеша. Оба правы, потому что Если много заказов и стоит списание, то после каждого списания нужно сбрасывать все кеши содержащие динамические данные
Метод работы с memcache взял из этой статьи Т.е. берем md5 хеш запроса и принимаем его за ключ. Если в memcache нет результат по ключу, то только тогда выполняем запрос к БД и сохраняем результат запроса в memcache Одна из основных задач - это поддержание всегда актуальных цен и остатков товара. Цены могут поменяться в любой момент. Синхронизация остатков производиться несколько раз в час. Можно кешировать, но только на пару минут, но есть ли в этом смысл? Попробую переписать запрос и изменить логику на получение товаров с ценами и остатками без кэширования.
ну так и сбрасывайте кеш Дело в том что вы берете хеш и не знаете что в нем в ОС ключ задается после Идентификатор products.Магазин.ГруппаПокупателей.хеш тогда можно спокойно его удалить cache-delete('product')
Действительно. Точечно сбросить хеш не получиться. На разные виды данных настроил разное время жизни кэша. В целом сбрасывать не приходиться, кроме экстренных случаев Очищаю $cache->memcache_flush() Думал, использовать префикс в виде имени вызываемой функции. Код: public function getCategory($category_id) { $name = __FUNCTION__; //Имя функции $key_cache = $name . $category_id; //Ключ memcache $get_result = $this->cache->get($key_cache); //Ищем значение в memcache по ключу if ($get_result) { return $get_result; } else { $query = $this->db->query("SELECT DISTINCT * FROM " . DB_PREFIX . "category c LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) WHERE c.category_id = '" . (int)$category_id . "'"); $this->cache->set($key_cache, $query->row, false, 3600); //Закэшируем на 1 час return $query->row; } }
В результате получился наглядный пример, почему после уроков Попова получаются сплошные гавнокодеры. Как использовать непосредственно memcache можно было посмотреть и в доках пыха - http://php.net/manual/ru/memcache.examples-overview.php А остальное просто по аналогии с обычным кешем в ОК. Туда надо дописывать ещё путь к файлу или имя класса, потому что названия функций могут дублироваться в разных файлах.
Уважаемый автор, вам нет необходимости так делать. Кеширование в OpenCart реализовано на уровне драйвера подключения к БД, поэтому он кеширует не страницу (каталог или статью), а конкретно запрос-ответ к БД (ключ-значние). Т.к. главная страница это все равно совокупность модулей (слайдер, баннеры, хиты продаж, скидки и пр.), то нужно проверять, что эти запросы кешируются (в вашем случае Memcache).
Так он и кеширует ответ (запрос) Для таблицы setting - это нормальное решение Иди сделать запрос, получить массив, а потом этот массив еще раз прогнать циклом Ошибка ТС В том что он кеширует объект, а не рузультат
Ну глянь как обрабатываются запросы.. Код: while ($row = $query->fetch_assoc()) { $data[] = $row; } $result = new \stdClass(); $result->num_rows = $query->num_rows; $result->row = isset($data[0]) ? $data[0] : array(); $result->rows = $data; Я на одном из проектов добавил несколько методов типа queryCusor getQueryRow - fetch таким образом избавившись от этого while ($row = $query->fetch_assoc()) { а сам while перенес в основной цикл Для высокоресурсных повысмло производительность и уменьшило потребление памяти.
Это требует много работы в моделях. Вообще, если уж работать над оптимизацией взаимодействия с базой, то начинать надо с интеграции нормальной библиотеки (а там курсор из коробки будет).
Мне это понадобилось, когда нужно было построить за один раз большую карту сайта (или какую-то выгрузку) Ибо нефик тягать весь кортеж по движку туда сюда.