Я храню результаты игр за неделю в таблице под названием pref_money :
# select * from pref_money limit 5;
id | money | yw
----------------+-------+---------
OK32378280203 | -27 | 2011-44
OK274037315447 | -56 | 2011-44
OK19644992852 | 8 | 2011-44
OK21807961329 | 114 | 2011-44
FB1845091917 | 774 | 2011-44
(5 rows)
А для победителей каждой недели я показываю медаль (и):
Я нахожу количество медалей для пользователя, набрав:
# select count(id) from (
select id,
row_number() over(partition by yw order by money desc) as ranking
from pref_money
) x
where x.ranking = 1 and id='OK260246921082';
count
-------
3
(1 row)
И этот запрос довольно дорогой:
# explain analyze select count(id) from (
select id,
row_number() over(partition by yw order by money desc) as ranking
from pref_money
) x
where x.ranking = 1 and id='OK260246921082';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=18946.46..18946.47 rows=1 width=82) (actual time=2423.145..2423.145 rows=1 loops=1)
-> Subquery Scan x (cost=14829.44..18946.45 rows=3 width=82) (actual time=2400.004..2423.138 rows=3 loops=1)
Filter: ((x.ranking = 1) AND ((x.id)::text = 'OK260246921082'::text))
-> WindowAgg (cost=14829.44..17182.02 rows=117629 width=26) (actual time=2289.079..2403.685 rows=116825 loops=1)
-> Sort (cost=14829.44..15123.51 rows=117629 width=26) (actual time=2289.069..2319.575 rows=116825 loops=1)
Sort Key: pref_money.yw, pref_money.money
Sort Method: external sort Disk: 4320kB
-> Seq Scan on pref_money (cost=0.00..2105.29 rows=117629 width=26) (actual time=0.006..22.566 rows=116825 loops=1)
Total runtime: 2425.001 ms
(9 rows)
Именно поэтому (и поскольку мой веб-сайт испытывает трудности во время пиковых нагрузок, когда в журнале pgbouncer отображается 50 запросов / с), я хотел бы кэшировать это значение и добавить столбец medals в другой таблица - pref_users :
pref=> \d pref_users;
Table "public.pref_users"
Column | Type | Modifiers
------------+-----------------------------+---------------
id | character varying(32) | not null
first_name | character varying(32) |
last_name | character varying(32) |
female | boolean |
avatar | character varying(128) |
city | character varying(32) |
lat | real |
lng | real |
login | timestamp without time zone | default now()
last_ip | inet |
medals | smallint | default 0
logout | timestamp without time zone |
Indexes:
"pref_users_pkey" PRIMARY KEY, btree (id)
Check constraints:
"pref_users_lat_check" CHECK ((-90)::double precision <= lat AND lat <= 90::double precision)
"pref_users_lng_check" CHECK ((-90)::double precision <= lng AND lng <= 90::double precision)
"pref_users_medals_check" CHECK (medals >= 0)
Я хотел бы создать cronjob, который будет запускаться каждые 15 минут, чтобы обновить этот столбец для всех пользователей в таблице pref_users :
*/15 * * * * psql -a -f $HOME/bin/medals.sql
Как видите, у меня почти все на месте. Моя проблема в том, что я еще не предложил оператор SQL для обновления столбца medals .
Любая помощь, пожалуйста?
Я использую PostgreSQL 8.4.8 с CentOS Linux 5.6 / 64 bit.
Спасибо!
Alex