База или кеширование?

Opik

Новичок
База или кеширование?

Здравствуйте!
У меня опять возник вопрос по производительности.
Как сделано сейчас:
В функции инициализации, данные из таблицы считываются в массив и кешируются через мемкеш (Если данные уже в кеше есть, то повторно данные не считываются).
Допустим имеем страницу - инвентарь персонажа в игре, где нужно вывести все вещи персонажа, которые лежат естессно в инвентаре и описанием(характиристики и прочее) вещи (что хранится в кеше).
И в тоге примерно такое:
PHP:
$query = mysql_query("SELECT * FROM equip WHERE owner = CHAR_ID");
while($row = mysql_fetch_assoc($query))
{
     $item = getItem($row['itemId']);
     $item['cond'] = $row['cond']; //  и ещё парочка свойств по анологии
     $items[] = $this->parseItem($item);
}
всё бы вроде ничего, но решил провести тесты и сравнить результат с обычным селектом. т.е с:
PHP:
$query = mysql_query("SELECT * FROM equip AS e
LEFT JOIN Item AS i ON(e.itemId = i.itemId)
WHERE owner = CHAR_ID");
while($row = mysql_fetch_assoc($query))
{
     $items[] = $this->parseItem($row);
}
Записал использование памяти и времени выполнения, вот что вышло:
sql:
Memory usage: 379992; action time: 0.037323; repeat: 1
Memory usage: 379992; action time: 0.119010; repeat: 10
Memory usage: 379992; action time: 0.233884; repeat: 20
mem:
Memory usage: 1338808; action time: 0.024803; repeat: 1
Memory usage: 1375400; action time: 0.286832; repeat: 10
Memory usage: 1375400; action time: 0.618568; repeat: 20
Т.е получается, что делая запрос с лефт джойн выигрываем и в скорости и в свободной памяти. Не будет ли грабель если передаю на 2 вариант (сложный запрос), при:
а) увеличении посетителей.
б) каких либо ещё факторов
?
 

Rammstein

PHPClub::News
Я вот тему, первый кусок кода и второй кусок кода связать всё никак не могу :)

По всей видимости в getItem(); у тебя спрятан ещё один запрос. Так? Если да, то лефт джоином ты сокращаешь количество обращений к БД, а передача данных серверу и обратно - достаточно длительный процесс. Отсуда можешь получить увеличение скорости.

Вообще, сложные запросы стоит использовать везде, где только это возможно. Простые запросы приемлемы в случае универсализации. Т.е., к примеру, ORM проще реализовать на простых запросах.

Итого: со сложными запросами больше времени убьёшь, но производительность повысится, с простыми всё будет проще - в основном свдётся к написанию отдельных PHP функций (таких как getItem()), но производительности при определённых обстоятельствах может упасть.

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

serglt

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

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

.des.

Поставил пиво кому надо ;-)
Код:
global $items;  // туда считывается всё из базы
для всех $items $id? То есть вы все закешированное из мемкэша перекачиваете в php массив?
 

Opik

Новичок
PHP:
if(($items = $memcache->get('items')) == false)
{
     $query = mysql_query("SELECT * FROM Item");
     $items = array();
     while($row = mysql_fetch_assoc($query))
     {
             $items[$row['item_id']][] = $row;
     }
      $memcache->set('items', $items, false, 0);
}
 

Rammstein

PHPClub::News
Автор оригинала: Opik
Rammstein

нет. сказал же - мемкеш.
PHP:
function getItem($id)
{
     global $items;  // туда считывается всё из базы
     return $items[$id];
}
Тогда понял. При маленьком количестве ещё более-менее оправдано. При больших, с индексами MySQL не поспоришь....
 

Falc

Новичок
Opik

Приведенный запрос с LEFT JOIN является весьма простым и эфективным, я полагаю что обычно у персонажа не так много вещей (следовательно строк возвращаемых запросом не так много). В варианте с "кешированием" выполняется много лишнего ПХП кода, который в итоге и получается медленее. Но если вытаскивать достаточно большое кол-во строк и подключать кучу справочников через LEFT JOIN, а данных в этих справочникак будет не много, то вариант с вытаскивание справочников в PHP массив будет работать быстрее. Вобщем тут надо выбирать способ в зависимости от ситуации: если извлекаемых данных много, а справочники маленькие, то перевес будет на стороне массива, если данных не много то перевес будет на стороне LEFT JOIN.
 

Opik

Новичок
Falc
спасибо за ответ.
Запрос:
[sql]
SELECT * FROM equip AS e
LEFT JOIN Item AS i ON(e.itemId = i.itemId)
WHERE owner = CHAR_ID
[/sql]
Таблица Item - небольшая, Ну 500 записей где то.
equip же побольше, там 40923 записей.(кол-во вещей у всех персонажей). Т.е данных тут немного возращает запрос, подключается только 1 справочник.
Выходит в этом случае лучше использовать LEFT JOIN.

Я правильно сделал выводы?
 

AnToXa

prodigy-одаренный ребенок
пардон, а зачем на каждый запрос получать _весь_ список items, который 40 с лишник тыщ позиций?

дык делайте N запросов в memcache по количеству вещей и все, или у вас там их 500?
 

Opik

Новичок
AnToXa
В мемкеш идут 500 записей. Из таблицы (Item). т.е описание вещи.
40к записей в equip, где мы узнаем какие вещи есть у перса.(по условию). Вроде нигде не получаем весь список (помимо считываения в кеш, который делается только 1 раз)
 

AnToXa

prodigy-одаренный ребенок
т.е. на каждый запрос.
1. читаем 500 записей из memcache в память пхп.
2. делаем select с условием, чтобы выбрать вещи версонажа из equip.
3. проходимся по вещам, выбирая описания из массива который получен на шаге 1.

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

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

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

-~{}~ 10.01.06 15:58:

кстати, вещи(т.е. items), возможно, стоит хранить как пхп-код.
этот код можно генерить из базы другим пхп скриптом например, т.к. список существующих вещей меняется редко.
при использовании аккселераторов это может дать выигрыш.
плюс т.к. вы все равно парсите данные из memcache в массив, то выигрываем еще за лишнем запросе к кешу.
 

.des.

Поставил пиво кому надо ;-)
и в любом случае стоит избегать больших массивов в php.
 

Opik

Новичок
.des.
AnToXa
имеет ли смысл 1 большой массив разбить на группы?
т.е:
$ar_battle = array ...
$ar_request = array...
чем всё в 1?

-~{}~ 10.01.06 21:51:

Например сейчас большой языковой файл только для боев, имеет ли смысл:
1) Разбить файл на части, и иклудить уже части, чем 1 большой
2) Массив разбить по категорям, и категории как раз уже назначить файлами.
3) Сейчас стоит считываение файла в мемкеш, может стоит это убрать т.к стоит еакселератор? и в итоге делаются лишние телодвижения?)

ПыСы: текущий размер файла 232 кб
 
Сверху