Кэширование запросов

Статус
В этой теме нельзя размещать новые ответы.

riki-tik

Новичок
Здравствуйте!
Для своего проекта использую простое кэширование запросов, если можно назвать это кэшированием.
Заключается в том, чтобы сохранять данные в глобальные переменные...
Т.е. происходит запрос на выборку пользователя с именем X:
Код:
SELECT id,name,avatar FROM users WHERE name = "X"
Допустим нашлось 3 пользователя:
Код:
array(
0 => 1,
1 => 5,
2 => 10
);
И в случае если будет такой же запрос происходить при текущей загрузке страницы, то я решил просто сохранять результаты запросов в суперглобальном массиве $GLOBALS. Единственное что меня смущает это название ключа запроса. Т.е. все запросы у меня хранятся в $GLOBALS['query_cache'], далее идет ключ запроса(это сам запрос) $GLOBALS['SELECT id,name,avatar FROM users WHERE name = "X"'] и результат.
В php(как и вообще в программировании) я новичок, но догадываюсь что вы меня сейчас будете критиковать за такие вещи. Я лишь прошу объяснить можно ли так делать и если нет, то почему? Можно ли в названии ключа массива использовать пробелы? Какая максимальная длинна названия ключа может быть?
И да, вы наверное меня раскритикуете тем что запросов может быть много и они все тогда останутся в памяти, но я использую лишь выборочные запросы которые могут повторяться...
 

CoolKid

Новичок
1. Используй md5($query) или sha1($query) - т.е. в качестве ключа используй хеш от запроса.
2. Старайся не использовать глобальные переменные, используй паттерн Registry в качестве хранилища или храни результаты кеширования в сессии
 
Последнее редактирование:

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
riki-tik, ты знаешь как работают индексы в mysql? Это мой наводящий вопрос. Ибо без первого, пока ты не упрешься в производительность БД, нет смысла придумывать кеширование.
 

riki-tik

Новичок
Как я и писал, я кэширую не все запросы, я просто хочу иметь такую возможность. Т.е. если запрос может использоваться в нескольких местах я хочу запомнить просто результат. Так нельзя делать?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
riki-tik, ты не ответил на мой вопрос, а это нехорошо.

Кешировать результаты выполнения запросов - распространенная практика. Только просто так ничего делать не надо, только потому, что тебе хочется. Надо четко объяснить почему ты решил ввести кеширование у себя в приложении.

PS: и да, на $GLOBALS делать не стоит.
 

riki-tik

Новичок
riki-tik, ты не ответил на мой вопрос, а это нехорошо.

Кешировать результаты выполнения запросов - распространенная практика. Только просто так ничего делать не надо, только потому, что тебе хочется. Надо четко объяснить почему ты решил ввести кеширование у себя в приложении.

PS: и да, на $GLOBALS делать не стоит.
Как работают я лишь примерно понимаю.
Причина проста, хочу предотвратить дубль запросов. Кэшироваться все подряд не будет, это будет как дополнительный параметр. Вот так я запрос к базе: DB::query( $sql ); И вторым булевым параметром идет решение кэшировать его или нет (по умолчанию false). А если DB::query( $sql, true); то запрос должен кэшироваться.
Я лишь боялся что это несусветная глупость и так вообще нельзя делать. Действительно наверное ключи нужно в md5 переводить...
Если в $GLOBALS нельзя хранить, то можете объяснить почему? Надо хранить внутри класса DB ?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
riki-tik, не знаю, не знаю. Любой лишний символ в запросе, пробел или перевод строки приведет к тому, что у тебя будет уже другой md5 и вытащить запрос из кеша ты не сможешь.

Если ты не знаешь как работают индексы, то советую изучить и только после этого - думать о том, чтобы кешировать что-то.

Может быть надо пересмотреть приложение, если у тебя запросы выполняются по 2-3 раза одни и теже, стоит результат записать в какое-то свойство у энного класса и использовать потом его?

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

Vano

Новичок
c0dex, я правильно понял? для создания одного ответа сервера у него гдето в коде могут повторяться запросы?
 

riki-tik

Новичок
Как работают я лишь примерно понимаю.
Причина проста, хочу предотвратить дубль запросов. Кэшироваться все подряд не будет, это будет как дополнительный параметр. Вот так я запрос к базе: DB::query( $sql ); И вторым булевым параметром идет решение кэшировать его или нет (по умолчанию false). А если DB::query( $sql, true); то запрос должен кэшироваться.
Я лишь боялся что это несусветная глупость и так вообще нельзя делать. Действительно наверное ключи нужно в md5 переводить...
Если в $GLOBALS нельзя хранить, то можете объяснить почему? Надо хранить внутри класса DB ?
Спасибо за объяснения!
c0dex, я правильно понял? для создания одного ответа сервера у него гдето в коде могут повторяться запросы?
Просто хочу предотвратить такую такие случаи.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Vano, что у него в коде - одному ему известно)
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Hello, при чем тут это? Человек хочет другого уровня кеш
 

CoolKid

Новичок
Хранить результаты кеша нужно в каком либо хранилище: либо это тупо файловая система, либо это Memcached или Redis сервер.
Если говорить сущностями и абстракциями у тебя должна быть сущность Cache и методы set, get, hasKey, delete, flush или что-то вроде того
Подсистема кеширования как таковая лежит на уровень ниже и при инициализации сущности Cache можно указывать какое именно хранилище тебе нужно.

Как-то так:

PHP:
<?php
Cache::init('filesystem');

$sql = "SELECT * FROM users";

if (!Cache::hasKey(md5($sql))) {
    $data = DB::query($sql)->fetchAssoc();
    Cache::set(md5($sql), $data, 600)); // последний параметр это ttl - время жизни кеша
} else {
    $data = Cache::get(md5($sql));
}

var_dump($data);
 

Вурдалак

Продвинутый новичок
CoolKid, а теперь расскажи как ты делаешь инвалидацию, как проверяешь можно ли кешировать запрос (UNIX_TIMESTAMP(), NOW(), etc.). Такая наивная тупая реализация никогда не будет работать.
 

CoolKid

Новичок
Она прекрасно работает именно в тех случаях в каких это нужно ТС
Тем более что он хочет не включить кеш глобального для всех запросов, а при каждом выборочном запросе указывать включать кеш или нет.
В этом случае всё тобой перечисленное проверяется человеком, который указывает вторым параметром true в DB::query()

А глобально да, она не сработает, я с тобой согласен
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху