forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PHP / MySQL (http://forum.boolean.name/forumdisplay.php?f=135)
-   -   Возможно ли оптимизировать получение данных из двух таблиц (http://forum.boolean.name/showthread.php?t=18025)

pax 26.03.2013 12:42

Возможно ли оптимизировать получение данных из двух таблиц
 
В общем есть две таблицы
user_items

и user_item_params


Получаю из них данные следующим образом:

PHP код:

public function items_getUserItems($user_id)
    {
        
$sth $this->dbh->prepare('SELECT * FROM user_items WHERE user = :user_id');
        
$sth->execute(array(
            
':user_id' => intval($user_id),
        ));

        
$items$sth->fetchAll(PDO::FETCH_ASSOC);

        
$sth $this->dbh->prepare('SELECT * FROM user_item_params WHERE item = :item_id');

        
$count count($items);
        for(
$i=0$i<$count$i++)
        {
            
$sth->execute(array(
                
':item_id' => intval($items[$i]['id']),
            ));
            
$items[$i]['params'] = $sth->fetchAll(PDO::FETCH_ASSOC);
        }

        return 
$items;
    } 

Возможно ли это оптимизировать и не делать для каждого юзер_итема запрос его параметров?

DStalk 26.03.2013 12:59

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
Я так понимаю тебе нужен JOIN? http://ru.wikipedia.org/wiki/Join_(SQL)

pax 26.03.2013 13:14

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
Мне надо передать на клиент результат в формате json, join мне даст одну таблицу, придется делать хитрый алгоритм для преобразования если я хочу, чтобы результат выглядел как сейчас.

DStalk 26.03.2013 13:34

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
оптимально все сделать одним запросом, а цикл потом для обработки все равно нужен, т.к. mysql в json может выбрать тока при EXPLAIN, и то с версии 5.6

вроде так:
PHP код:

SELECT FROM user_items LEFT JOIN user_item_params ON user_items.items=user_item_params.item WHERE user=userid 


pax 26.03.2013 14:08

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
Посоветовали мне получить параметры итемов отдельно одним запросом и получилось следующее
PHP код:

public function items_getUserItems($user_id)
    {
        
$sth $this->dbh->prepare('SELECT * FROM user_items WHERE user = :user_id');
        
$sth->execute(array(
            
':user_id' => intval($user_id),
        ));
 
        
$items $sth->fetchAll(PDO::FETCH_ASSOC);
 
        
$count count($items);
 
        
$item_ids = array();
        
$item_index = array();
        for(
$i=0$i<$count$i++)
        {
            
$items[$i]['params'] = array();
            
$item $items[$i];
            
$item_ids[] = $item['id'];
            
$item_index[$item['id']] = $i;
        }
 
        
$sth $this->dbh->prepare('SELECT * FROM user_item_params WHERE item IN ('.implode(', '$item_ids).');');
        
$sth->execute();
        
$item_params $sth->fetchAll(PDO::FETCH_ASSOC);
 
        foreach(
$item_params as $item_pram)
        {
            
$item $item_pram['item'];
            unset(
$item_pram['item']);
            
$items[$item_index[$item]]['params'][] = $item_pram;
        }
 
        return 
$items;
    } 


А еще я обдумывал вариант с параметрами в поле первой таблицы в виде json строки...

moka 26.03.2013 15:06

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
Сразу подмечу, что если у тебя индексация в обоих таблицах хорошо настроина, то запросы будут весьма оптимальны даже при двух запросах.
Но. Тут важна суть не в запросах, а в том кто эти данные получает и что с ними делает.

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

Да и насчёт JSON'а, я тебе настоятельно рекомендую пересмотреть хотя бы на будущее представление о том как данные хранятся в БД. Ты используешь SQL базу данных, с таблицами, но преобразуешь в вложенные JSON документы.
Посмотри в сторону NoSQL баз данных, таких как MongoDB - легко ставиться, очень проста в использовании. Важный плюс в том что там нету таблиц, и всяких JOIN'ов (хотя это сильно влияет на то как данные хранятся, и не всегда подойдёт), зато есть сложные формы объектов, с вложенностями, массивами, хеш таблицами и т.п. Что как я вижу просто идеально подходит под то что ты пытаешься сделать в коде выше.

pax 26.03.2013 15:53

Ответ: Возможно ли оптимизировать получение данных из двух таблиц
 
Спасибо за советы. NoSQL в данном случае не подходит, т.к. я на хостинг ничего не могу поставить сам.

По поводу получения - данные меняться будут редко, и не во время боя. И я всетаки решил сделать все в первой таблице. Я создал в ней текстовое поле params и в виде json буду хранить там параметры.

В итоге получилось вот так:
PHP код:

public function items_getUserItems($user_id)
    {
        
$sth $this->dbh->prepare('SELECT * FROM user_items WHERE user = :user_id');
        
$sth->execute(array(
            
':user_id' => intval($user_id),
        ));

        
$items $sth->fetchAll(PDO::FETCH_ASSOC);

        
$count count($items);

        for(
$i=0$i<$count$i++)
        {
            
$items[$i]['params'] = json_decode($items[$i]['params'], true);
            if(
$items[$i]['params'] == null)
            {
                unset(
$items[$i]['params']);
            }
        }

        return 
$items;
    } 



Часовой пояс GMT +4, время: 12:53.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot