0

有2张桌子:

  • challenge
  • entry(每个挑战有很多条目)

要输入挑战,需要输入他们的电子邮件姓名(用于排行榜) - 没有注册/身份验证过程,因此emailleaderboard_name都记录在entry表格中的每个条目中:

CREATE TABLE public.entry
(
    id bigint NOT NULL DEFAULT nextval('entry_id_seq'::regclass),
    challenge_id bigint NOT NULL,
    date_created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
    email text COLLATE pg_catalog."default" NOT NULL,
    is_removed boolean NOT NULL DEFAULT false,
    total_points integer NOT NULL DEFAULT 0,
    CONSTRAINT entry_pkey PRIMARY KEY (id)
)

使用这种方法,可以在一次质询中多次使用相同的电子邮件值。换句话说,可以创建具有相同电子邮件的多个条目。

现在,获取得分最高的不同电子邮件的查询非常简单:

SELECT DISTINCT ON (email)
  id as entry_id, total_points
FROM  entry
WHERE challenge_id = 1
  AND is_removed = false
  AND total_points > 0
ORDER BY email, total_points DESC, date_created;

在这里,我们不希望出现以下条目:

  • a) 被管理员删除 ( is_removed = false)
  • b) 得分为零 ( total_points > 0)

challenge_id = 1也是必不可少的,因为它通过其 ID 将条目限制为特定挑战。

date_created此外,如果有许多具有相同分数的电子邮件,则order by会为每封电子邮件选择最早的条目。这可确保每封电子邮件选择的条目始终相同。

当我尝试构建查询计划程序将使用的索引时,就会出现问题。

我尝试在以下位置创建索引:

  • 3列:email, total_points DESC, date_created
  • 5列:challenge_id, is_removed, email, total_points DESC, date_created

EXPLAIN不断返回entry表的 Seq Scan。


奖金问题 - 如何有效地只选择前 N 个条目total_points DESC, date_created ASC?最简单的方法是用另一个查询包装这个查询,但有没有更好的方法?

4

0 回答 0