Кэш запросов в index.php

Тема в разделе "OpenCart", создана пользователем Den1a, 10 авг 2017.

  1. Den1a

    Den1a

    Регистрация:
    16 авг 2013
    Сообщения:
    55
    Симпатии:
    3
    Здравствуйте.
    • Запустил 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");

    Заранее благодарен.
     
  2. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Зачем?
    Кешировать имеет смысл тяжёлые запросы связанные с контентом, а не лёгкие связанные с работой самого движка. В MySQL ведь тоже есть кеширование и запросы из index.php в виду своей частоты и статичности должны попадат в тот кеш.

    Но если сильно хотите кешировать, надо просто перенести инициализацию кеша выше инициализации базы, а дальше вызывать как обычно, но без $this.
     
    Den1a нравится это.
  3. Den1a

    Den1a

    Регистрация:
    16 авг 2013
    Сообщения:
    55
    Симпатии:
    3
    Решил даже не обращаться к БД по таким запросам, т.к. они не меняются, а вызываются на каждой странице.
    Судя по графику нагрузки в часы пик начинает подседать MySQL. Решил как можно больше снять с нее работы.
    Не кэшировал запросы, где выбираются цены и остатки товара, для поддержания актуальности данных.
    А категории, меню, настройки и т.д. отправил в memcached

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

    В файле index.php сделал как вы подсказали. Запрос благополучно ушел в кэш.

    [​IMG]
     
  4. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    А зачем вы отдельно sql для ключа захешировали, а потом заново его в сам запрос вписали?
    Надо загнать sql в переменную и потом использовать её в обоих местах.
    Во-первых, дублирование кода - это плохо, а во-вторых, если вы в будущем хотя бы один символ измените в этом sql (в любом из двух), ключ перестанет соответствовать самому запросу.

    А среди запросов с ценами есть и одни из самых нагруженных в ОК и их имеет смысл кешировать в первую очередь! У вас же цены не меняются каждые два часа? А после выгрузки из 1С или ещё какого-то обновления данных, можно просто вручную сбросить кеш.
     
  5. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    На самом деле ключ уникализируется за счет (int)$config->get('config_store_id')
    А все остальное считай "солью"

    Но я бы сравнил время доступа к данным при чтении из базы и из кеша.

    Оба правы, потому что
    Если много заказов и стоит списание, то после каждого списания нужно сбрасывать все кеши содержащие динамические данные
     
  6. Den1a

    Den1a

    Регистрация:
    16 авг 2013
    Сообщения:
    55
    Симпатии:
    3
    Метод работы с memcache взял из этой статьи
    Т.е. берем md5 хеш запроса и принимаем его за ключ.
    Если в memcache нет результат по ключу, то только тогда выполняем запрос к БД и сохраняем результат запроса в memcache

    Одна из основных задач - это поддержание всегда актуальных цен и остатков товара. Цены могут поменяться в любой момент.
    Синхронизация остатков производиться несколько раз в час.

    Можно кешировать, но только на пару минут, но есть ли в этом смысл?
    Попробую переписать запрос и изменить логику на получение товаров с ценами и остатками без кэширования.
     
  7. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    ну так и сбрасывайте кеш

    Дело в том что вы берете хеш и не знаете что в нем
    в ОС ключ задается после Идентификатор

    products.Магазин.ГруппаПокупателей.хеш

    тогда можно спокойно его удалить cache-delete('product')
     
  8. Den1a

    Den1a

    Регистрация:
    16 авг 2013
    Сообщения:
    55
    Симпатии:
    3
    Действительно. Точечно сбросить хеш не получиться.
    На разные виды данных настроил разное время жизни кэша.
    В целом сбрасывать не приходиться, кроме экстренных случаев :Smile:
    Очищаю $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;
            }
        }
     
  9. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    В результате получился наглядный пример, почему после уроков Попова получаются сплошные гавнокодеры. Как использовать непосредственно memcache можно было посмотреть и в доках пыха - http://php.net/manual/ru/memcache.examples-overview.php А остальное просто по аналогии с обычным кешем в ОК.

    Туда надо дописывать ещё путь к файлу или имя класса, потому что названия функций могут дублироваться в разных файлах.
     
  10. iMateo

    iMateo

    Регистрация:
    23 фев 2013
    Сообщения:
    23
    Симпатии:
    2
    Уважаемый автор, вам нет необходимости так делать.
    Кеширование в OpenCart реализовано на уровне драйвера подключения к БД, поэтому он кеширует не страницу (каталог или статью), а конкретно запрос-ответ к БД (ключ-значние). Т.к. главная страница это все равно совокупность модулей (слайдер, баннеры, хиты продаж, скидки и пр.), то нужно проверять, что эти запросы кешируются (в вашем случае Memcache).
     
  11. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    Так он и кеширует ответ (запрос)
    Для таблицы setting - это нормальное решение

    Иди сделать запрос, получить массив, а потом этот массив еще раз прогнать циклом
    Ошибка ТС
    В том что он кеширует объект, а не рузультат
     
  12. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Зачем?
     
  13. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    Ну глянь как обрабатываются запросы..
    Код:
                    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 перенес в основной цикл

    Для высокоресурсных повысмло производительность и уменьшило потребление памяти.
     
  14. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Это требует много работы в моделях.

    Вообще, если уж работать над оптимизацией взаимодействия с базой, то начинать надо с интеграции нормальной библиотеки (а там курсор из коробки будет).
     
  15. chukcha

    chukcha

    Регистрация:
    9 окт 2014
    Сообщения:
    448
    Симпатии:
    119
    Мне это понадобилось, когда нужно было построить за один раз большую карту сайта (или какую-то выгрузку) Ибо нефик тягать весь кортеж по движку туда сюда.