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=17836)

pax 06.02.2013 07:36

Ответ: Добавить запись если не существует.
 
Да мне так и надо. Теперь я думаю что мне надо искать по параметрам тоже... Т.е. получить список пользователей отфильтрованный по какому либо параметру и отсортированный по значению параметра - таблица рекордов например. Пока появилась мысль дублировать поле parameter и добавить ему индекс, а для сортировки тоже нужен индекс для значения параметра?

moka 06.02.2013 14:52

Ответ: Добавить запись если не существует.
 
По сути не нужны индексы для сортировки.
Единственная разница в том что если ты будешь делать запросы к данным, заместо прямого доступа по индексу, бд будет листать все данные логически отфильтровывая.
Следственно, тут если нужна хорошая скорость, либо использовать индексы (но и они не всегда спасают), либо завезти отдельную таблицу которая будет обновляться в бд периодически, и выдавать её - получается кеш. Это самый шустрый вариант.

Просто когда речь будет идти о десятках тысяч игроков, то не индексированный поиск и сортировка не будет быстрой затеей.

pax 06.02.2013 15:13

Ответ: Добавить запись если не существует.
 
Отдельная таблица - хорошо, сделаю раз N минут обновление. Но индексы я создам. Создал индекс на поле parameter. Первый раз почему-то ругалось. Теперь норм)

pax 06.02.2013 15:29

Ответ: Добавить запись если не существует.
 
Еще интересно, такие запросы это очень плохо?
PHP код:

SELECT FROM `user_params
WHERE user 49 AND parameter 
      (
SELECT id FROM parameters WHERE name 'frags' LIMIT 1


moka 06.02.2013 19:32

Ответ: Добавить запись если не существует.
 
Это называется Subquery, и если он находится во внешней части запроса (WHERE), то это будет произведено один раз перед главным запросом, и затем будет использовано.
А вот если ты сделаешь подобное до FROM - для значения, то такой Subquery будет запущен для каждой строки которая будет выведена (учитывая возможный LIMIT).

По сути это ок.
Вопрос, у тебя как понимаю параметр это не только имя, и id, а что-то ещё, типо тип значения, минимальное / максимальное значение? Если это всё же что-то простое, то я не вижу необходимости иметь отдельную таблицу. Если же сложное - то оправдано.

pax 06.02.2013 20:20

Ответ: Добавить запись если не существует.
 
Я тут возможно подумаю о преобразовании поля parameter в тип enum, чтобы не получать id параметров из другой таблицы по имени. Сейчас таблица parameters просто список параметров с их id.

moka 06.02.2013 22:39

Ответ: Добавить запись если не существует.
 
Цитата:

Сообщение от pax (Сообщение 251945)
Я тут возможно подумаю о преобразовании поля parameter в тип enum, чтобы не получать id параметров из другой таблицы по имени. Сейчас таблица parameters просто список параметров с их id.

А почему тебе просто не использовать в таблице user_params в поле param сразу имя параметра типо: armor, health, speed и т.п.?
Они индексируются хорошо, и поиск нормально по ним тоже если индексированы.
Тем самым и читаемы, и одна таблица заместо двух.

pax 07.02.2013 07:14

Ответ: Добавить запись если не существует.
 
да хотел не тратить лишней памяти

Randomize 07.02.2013 08:36

Ответ: Добавить запись если не существует.
 
Кстати при таком подходе и производительность будет выше, а затрачиваемой памяти будет куда меньше.
Хотя главное тут не память, а количество обращений к файловой системе.

pax 08.02.2013 07:50

Ответ: Добавить запись если не существует.
 
В общем решил отказаться от Enum вот почему:
http://www.mysqlperformanceblog.com/...hat-is-faster/
Цитата:

The problem we had with ENUM-fields; When we wanted to add a ‘type’ to an ENUM-field (or change the definition of the field in any way), MySQL often did a complete rewrite of that table. For some of our bigger tables (think tens of millions of records), this could take up to a few hours sometimes, which meant downtime. So for a few cases we decided to switch from ENUM’s to TINYINT’s because this eliminates the need for a change in table definition.
и пришел к выводу что лучше сделать в php вот так:
PHP код:

$config = array(
        ...,
        
'user_params' => array(
            
'frags' => 1,
            
'deaths' => 2,
            
'wins' => 3,
            
'fails' => 4,
            
'xp' => 5,
            
'money' => 6,
            
'golds' => 7
        
),
       ); 

и поле объявить как tinyint

Randomize 08.02.2013 11:20

Ответ: Добавить запись если не существует.
 
Цитата:

Сообщение от pax (Сообщение 252107)
PHP код:

$config = array(
        ...,
        
'user_params' => array(
            
'frags' => 1,
            
'deaths' => 2,
            
'wins' => 3,
            
'fails' => 4,
            
'xp' => 5,
            
'money' => 6,
            
'golds' => 7
        
),
       ); 


O__o
Если я правильно понял это константы.
PHP код:

<?
class UserParams{
     const FRAGS = 1;
     const DEATHS = 2;
     const WINS = 3;
}
// ну и юзать так
UserParams::MONEY
?>


pax 08.02.2013 13:09

Ответ: Добавить запись если не существует.
 
чтобы понятнее было чего я хочу добиться:

PHP код:

$config = array(
...
    
'user_params' => array(
        
'frags' => 1,
        
'deaths' => 2,
        
'wins' => 3,
        
'fails' => 4,
        
'xp' => 5,
        
'money' => 6,
        
'golds' => 7
    
),
    
'user_params_invert' => array(
        
=> 'frags',
        
=> 'deaths',
        
=> 'wins',
        
=> 'fails',
        
=> 'xp',
        
=> 'money',
        
=> 'golds'
    
),
); 

PHP код:

public function user_updateParameter($id$parameterName$value)
    {
        
$param $this->config['user_params'][$parameterName];
        if (isset(
$param)) {
            
$sth $this->dbh->prepare('INSERT INTO user_params (user, parameter, value) VALUES (:user, :parameter, :value1) ON DUPLICATE KEY UPDATE  value = value + :value2');
            
$sth->execute(array(
                
':user' => intval($id),
                
':parameter' => $param,
                
':value1' => intval($value),
                
':value2' => intval($value)
            ));
        }
    } 

PHP код:

public function user_getParameters($id)
    {
        
$sth $this->dbh->prepare('SELECT parameter, value FROM user_params WHERE user = ?');
        
$sth->execute(array(intval($id)));
        
$params $sth->fetchAll(PDO::FETCH_NUM);
        
$nameValue = array();
        
$pi = &$this->config['user_params_invert'];
        foreach (
$params as $keyValue) {
            
$nameValue[$pi[$keyValue[0]]] = $keyValue[1];
        }
        return 
$nameValue;
    } 



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

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