使用分组加速词云选择

问题描述 投票:0回答:1

我目前正在开展一个为《纽约时报》创建词云的项目。因此,我从 NYT 的 API 中抓取所有文章,然后将文章的日期、文章的 href 以及该文章中提到的所有标记及其数量存储在 mysql 数据库中。 该模型如下所示:

Date (dateID PK, publish_date Date)
Article (articleID PK, href char(300), dateID FK)
Token (tokenID PK, name char(100), articleID FK)

我还对

publish_date
和标记
name
建立了索引,这已经使查询速度提高了一倍。

查询的任务是返回指定日期范围内发布的所有文章中最多 100 个代币及其总金额。看起来像这样:

WITH 
    dateID as (
        SELECT dateID
        FROM date 
        WHERE publish_date >= '1999-12-31'
          AND publish_date <= '2023-12-31'
    ),
    articleIDs as (
        SELECT articleID
        FROM article
        WHERE dateID IN (TABLE dateID)
    )
SELECT t.name as name, sum(t.amount) as amount
FROM token t
WHERE t.articleID IN (TABLE articleIDs)
AND t.name > '@'
GROUP BY t.name
ORDER BY amount DESC
LIMIT 100;

仅供参考:这是由 aws 托管的

innoDB
,带有 mysql 版本
8.0.33

我已经限制了从《纽约时报》获取的时间范围,现在数据库中已加载 2012 - 2023 年。 在当前设置下,查询大约需要 100 秒才能完成,仅包含 6,458,501 个令牌。我发现,最低效的部分是分组依据,因此我研究了通过索引扫描进行优化,但发现这不适用于我的用例。

我怎样才能尽快做到这一点?我的目标是 5 秒左右。

编辑:执行计划: Execution plan

mysql group-by query-optimization
1个回答
0
投票

对于这样的查询来说,每秒六万行并不是病态的慢。如果您的应用程序需要经常使用此结果集,则需要在某处保留它的副本。无论如何,近四分之一个世纪的历史新闻中使用的前 100 个代币的变化非常缓慢,如果您每天只重新计算一次结果集,甚至每周一次,您的用户将不会注意到。

如果您希望提高效率,下一步最好是完全消除

date
表,并将每个
publish_date
存储在
article
表中。那么你的查询将如下所示。

WITH 
    articleIDs as (
        SELECT articleID
        FROM article
        WHERE publish_date >= '1999-12-31'
          AND publish_date <= '2023-12-31'
    )
SELECT t.name as name, sum(t.amount) as amount
FROM token t
WHERE t.articleID IN (TABLE articleIDs)
AND t.name > '@'
GROUP BY t.name
ORDER BY amount DESC
LIMIT 100;

dateID
值来参考你的日期是没有任何好处的。 SQL 擅长按日期范围进行过滤。即使您由于某种未提及的原因确实需要单独的日期表,也请使用其
date
值作为主键,而不是
dateID

article.publish_date
上的索引会有所帮助。并且,您应该在
token
表上尝试这两个复合索引。其中之一会有所帮助,查询计划会告诉您哪一个。

CREATE INDEX name_id ON token(name, articleID);
CREATE INDEX id_name ON token(articleID, name);
© www.soinside.com 2019 - 2024. All rights reserved.