Я заранее извиняюсь, если этот вопрос слишком специфичен, но я считаю, что это довольно типичный сценарий: join
и group by
s увязку с дбом и лучший способ обойти его. Моя конкретная проблема заключается в том, что мне нужно создать табло на основе:Временная таблица заболачивания базы данных - как оптимизировать?
- пьес (идентификатор пользователя, GameID, оценка) 40M строк
- игр (GameID) 100K строк
- app_games (AppID, GameID), то есть, игры сгруппированы в приложениях и есть общий балл за приложение, которое является суммой всех связанных с ним игр < 20 строк
пользователи могут играть в несколько раз, и их лучший результат для каждой игры записывается. Сформулировать запрос легко, я сделал несколько вариантов, но у них есть противная тенденция запираться в «скопировании временной таблицы» в течение 30-60 секунд при загрузке.
Что я могу сделать? Существуют ли переменные сервера, которые я должен настраивать, или есть способ переформулировать запрос, чтобы сделать его быстрее? Производная версия запроса, который я использую выглядит следующим образом (минус таблица пользователей присоединиться, чтобы захватить имя):
select userID,sum(score) as cumscore from
(select userID, gameID,max(p.score) as score
from play p join app_game ag using (gameID)
where ag.appID = 1 and p.score>0
group by userID,gameID) app_stats
group by userid order by cumscore desc limit 0,20;
Или как временную таблицу:
drop table if exists app_stats;
create temporary table app_stats
select userID,gameID,max(p.score) as score
from play p join app_game ag using (gameID)
where ag.appID = 1 and p.score>0
group by userid,gameID;
select userID,sum(score) as cumscore from app_stats group by userid
order by cumscore desc limit 0,20;
У меня есть индексы, как следует:
show indexes from play;
+-------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| play | 0 | PRIMARY | 1 | playID | A | 38353712 | NULL | NULL | | BTREE | |
| play | 0 | uk_play_uniqueID | 1 | uniqueID | A | 38353712 | NULL | NULL | YES | BTREE | |
| play | 1 | play_score_added | 1 | dateTimeFinished | A | 19176856 | NULL | NULL | YES | BTREE | |
| play | 1 | play_score_added | 2 | score | A | 19176856 | NULL | NULL | | BTREE | |
| play | 1 | fk_playData_game | 1 | gameID | A | 76098 | NULL | NULL | | BTREE | |
| play | 1 | user_hiscore | 1 | userID | A | 650062 | NULL | NULL | YES | BTREE | |
| play | 1 | user_hiscore | 2 | score | A | 2397107 | NULL | NULL | | BTREE | |
+-------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
Я согласен с сохранением итогов игрока. –
Какие функции? Мы используем memcached, чтобы я мог кэшировать все это как массив, а затем просто изменять элементы, которые нужно изменить, получая/устанавливая один и тот же элемент. По какой-то причине я не видел такого memcached, как это (хотя я думал об этом) - вроде как наполовину к типу nosql типа db. – mmdanziger
Memcached не так хорош для этого (если вам нужно обновить результаты в режиме реального времени), потому что вы не можете легко получить список результатов. redis имеет «сортированные наборы», которые так хорошо подходят для вашего случая использования, что, если я правильно помню, это практически пример в их документации: http://redis.io/topics/data-types#sorted-sets –