我提出了以下选择查询:
SELECT row_number() OVER(ORDER BY value DESC, id) AS rank_global,
row_number() OVER(PARTITION BY country ORDER BY value DESC, id) AS rank_country,
*
FROM rate
ORDER BY value DESC, id
LIMIT 100000
有没有办法加快这个查询,或者有另一种方法可以做同样的事情?我创建了btree(值desc,id)和(country,value desc,id)索引,但仍需要很长时间才能完成。
示例:
创建一个表并使用具有随机值列和随机国家/地区的用户填充该表:
CREATE TABLE rate
(
id serial NOT NULL,
name text,
value integer NOT NULL DEFAULT 0,
country character varying,
CONSTRAINT rate_pkey PRIMARY KEY (id)
);
INSERT INTO rate
(SELECT n, ('user_'||n), (random()*30)::int, ('country_'||(random()*3)::int)
FROM generate_series(0,10) AS n);
CREATE INDEX rate_country_value_id_index
ON rate
USING btree(country, value DESC, id);
CREATE INDEX rate_value_id_index
ON rate
USING btree(value DESC, id);
表格内容:
id name value country
0 user_0 28 country_2
1 user_1 24 country_2
2 user_2 29 country_1
3 user_3 11 country_1
4 user_4 16 country_1
5 user_5 28 country_0
6 user_6 3 country_1
7 user_7 7 country_1
8 user_8 28 country_1
9 user_9 4 country_0
10 user_10 29 country_1
然后我创建物化视图:
CREATE MATERIALIZED VIEW rate_view AS
SELECT row_number() OVER (ORDER BY value DESC, id) AS rgl,
row_number() OVER (PARTITION BY country ORDER BY value DESC, id) AS rc,
*
FROM rate
ORDER BY value DESC, id;
查看内容(rgl - 全球排名,rc - 按国家/地区排名):
rgl rc id name value country
1 1 2 user_2 29 country_1
2 2 10 user_10 29 country_1
3 1 5 user_5 28 country_0
4 1 0 user_0 28 country_2
5 3 8 user_8 28 country_1
6 2 1 user_1 24 country_2
7 4 4 user_4 16 country_1
8 5 3 user_3 11 country_1
9 6 7 user_7 7 country_1
10 2 9 user_9 4 country_0
11 7 6 user_6 3 country_1
现在我可以创建复杂的查询来选择排名最接近的用户及其邻居的排名。全球和国家。
例如,(在视图上创建(value,id)和(rgl)索引之后)这里是全球前50名和最近排名为5999942的用户:
(
WITH closest_rank AS
(
SELECT rgl FROM rate_view
WHERE value <= 9999942
ORDER BY value DESC, id ASC
LIMIT 1
)
SELECT rgl, name, value
FROM rate_view
WHERE rgl > (SELECT rgl-3 FROM closest_rank )
ORDER BY rgl ASC
LIMIT 5
)
UNION
SELECT rgl, name, value
FROM rate_view
WHERE rgl <=50
ORDER BY rgl;