如何采用按单独列排序的 DISTINCT ON 子查询并使其快速?

2024-02-25

(又名 - 查询和数据与问题非常相似“选择按某列排序且在另一列上不同的行 https://stackoverflow.com/questions/9796078/selecting-rows-ordered-by-some-column-and-distinct-on-another“,我怎样才能让它运行得更快)。Postgres 11。

我有桌子prediction with (article_id, prediction_date, predicted_as, article_published_date)表示分类器对一组文章的输出。

新文章经常添加到单独的表中(由 FK 表示)article_id),并且当我们调整分类器时会添加新的预测。

样本数据:

| id      | article_id |  predicted_as | prediction_date | article_published_date
| 1009381 | 362718     |  negative     | 2018-07-27      | 2018-06-26
| 1009382 | 362718     |  positive     | 2018-08-12      | 2018-06-26
| 1009383 | 362719     |  positive     | 2018-08-13      | 2010-09-22
| 1009384 | 362719     |  positive     | 2018-09-28      | 2010-09-22
| 1009385 | 362719     |  negative     | 2018-10-01      | 2010-09-22

创建表脚本:

create table prediction
(
    id serial not null
        constraint prediction_pkey
            primary key,
    article_id integer not null
        constraint prediction_article_id_fkey
            references article,
    predicted_as classifiedas not null,
    prediction_date date not null,
    article_published_date date not null
);

create index prediction_article_id_prediction_date_idx
    on prediction (article_id asc, prediction_date desc);

我们经常想查看每篇文章的最新分类。为此,我们使用:

SELECT DISTINCT ON (article_id) article_id, id, article_published_date
FROM prediction
ORDER BY article_id, prediction_date desc

它返回类似:

| id     | article_id |  predicted_as | prediction_date | article_published_date
| 120950 | 1          | negative      | 2018-06-29      | 2018-03-25
| 120951 | 2          | negative      | 2018-06-29      | 2018-03-19

索引打开(article_id, prediciton_date desc),这个查询运行得非常快(~15ms)。这是解释计划:

Unique  (cost=0.56..775374.53 rows=1058394 width=20)
  ->  Index Scan using prediction_article_id_prediction_date_id_idx on prediction  (cost=0.56..756071.98 rows=7721023 width=20)

到目前为止,一切都很好。

当我想按article_published_field 对此结果进行排序时,就会出现问题。例如:

explain (analyze, buffers)
select *
  from (
         select distinct on (article_id) article_id, id, article_published_date
         from prediction
         order by article_id, prediction_date desc
       ) most_recent_predictions
  order by article_published_date desc
  limit 3;

这可行,但查询需要大约 3-4 秒才能运行,因此直接用于响应 Web 请求太慢。

以下是解释计划:

Limit  (cost=558262.52..558262.53 rows=3 width=12) (actual time=4748.977..4748.979 rows=3 loops=1)
  Buffers: shared hit=7621849 read=9051
  ->  Sort  (cost=558262.52..560851.50 rows=1035593 width=12) (actual time=4748.975..4748.976 rows=3 loops=1)
        Sort Key: most_recent_predictions.article_published_date DESC
        Sort Method: top-N heapsort  Memory: 25kB
        Buffers: shared hit=7621849 read=9051
        ->  Subquery Scan on most_recent_predictions  (cost=0.43..544877.67 rows=1035593 width=12) (actual time=0.092..4508.464 rows=1670807 loops=1)
              Buffers: shared hit=7621849 read=9051
              ->  Result  (cost=0.43..534521.74 rows=1035593 width=16) (actual time=0.092..4312.916 rows=1670807 loops=1)
                    Buffers: shared hit=7621849 read=9051
                    ->  Unique  (cost=0.43..534521.74 rows=1035593 width=16) (actual time=0.090..4056.644 rows=1670807 loops=1)
                          Buffers: shared hit=7621849 read=9051
                          ->  Index Scan using prediction_article_id_prediction_date_idx on prediction  (cost=0.43..515295.09 rows=7690662 width=16) (actual time=0.089..3248.250 rows=7690662 loops=1)
                                Buffers: shared hit=7621849 read=9051
Planning Time: 0.130 ms
Execution Time: 4749.007 ms

有什么方法可以使这个查询运行得更快,或者我是否必须刷新物化视图或设置触发系统来快速获取这些数据?

以供参考:

  • the prediction表有 770 万行
  • 有 170 万个不同的article_id是在prediction table
  • 有一个索引(article_id, prediciton_date desc)以及一对一article_published_date desc
  • VACUUM ANALYSE已运行

我想知道你是否可以做到这一点:

select article_id, id, article_published_date
from prediction p
where p.prediction_date = (select max(p2.prediction_date)
                           from prediction p2
                           where p2.article_id = p.article_id
                          )
order by article_published_date desc;

然后使用这两个索引:

  • (article_published_date desc, prediction_date, article_id, id)
  • (article_id, prediction_date desc).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何采用按单独列排序的 DISTINCT ON 子查询并使其快速? 的相关文章

随机推荐

  • TDirect2DCanvas 速度慢还是我做错了什么?

    在寻找替代 GDI 的替代品时 我试图测试 Delphi 的 2010TDirect2D画布Windows 7 中的性能 我通过使用 Direct2D 绘制一条巨大的折线来测试它 结果速度慢得离谱 即使数据量比我使用 GDI 运行相同测试的
  • Instagram API 不返回关注者

    我已通过 Instagram 进行身份验证 并且获得了具有范围的访问令牌follower list 然后我尝试获取我的关注者列表 https api instagram com v1 users self followed by acces
  • 未知的指令类型“toctree”。 Pycharm 出错,但 index.html 有效

    在 PyCharm 中工作时 我在 Sphinx 中创建的文档的预览模式显示 System Message ERROR 3
  • “Where like”子句使用 2 列的串联值与雄辩

    我有一个查询 在多个列中搜索一个术语 其中之一必须是全名 我已将姓名和姓氏分开 因此在搜索时必须连接这两个值 我现在只有搜索名字 我如何将连接添加到姓氏 我正在调查突变体 但我不知道这是否是正确的方法 public function sea
  • 初学者的 C 套接字编程

    我刚刚开始学习套接字编程 发现它非常有趣 目前我正在制作服务器和客户端在同一台计算机上因此我可以拥有IP地址作为环回地址 127 0 0 1一切似乎都运行良好 但现在我正在考虑拥有两台计算机并做这件事 我有以下问题 假设一台计算机是服务器
  • Android SQLiteConstraintException:错误代码19:约束失败

    我已经看到了有关此异常的其他问题 但所有这些问题似乎都通过解决方案解决了 即已存在指定主键的行 对我来说似乎并非如此 我尝试用双引号替换字符串中的所有单引号 但出现了同样的问题 我正在尝试通过执行以下操作将一行插入到我创建的 SQLite
  • 使用 T & F 代替 TRUE & FALSE 有什么问题吗?

    我注意到使用T and F代替TRUE and FALSER 中的函数给了我相同的结果 当然 T and F更简洁 但是 我明白了TRUE and FALSE被更频繁地使用 我想知道两者之间有什么区别吗 使用有什么问题吗T and F T
  • oracle sqlplus中获取sql脚本的执行时间

    我有一个脚本 用于将数据加载到 Oracle 中的表中 通过插入语句列表 如何获取整个加载过程的执行时间 我尝试过set timing on 但这给了我每个插入语句的持续时间 而不是整个过程的持续时间 脚本如下所示 spo load log
  • 是否可以将 supertest 与 hapi 一起使用?

    我用的是hapi 不是express 超级测试还应该有效吗 如果是这样 有没有一种快速方法可以更改我的代码以使其运行 我的测试看起来像这样 基于文档 https github com visionmedia supertest import
  • 如何在 Mockito 中模拟 CompletableFuture 的完成

    我想模拟当某个代码被调用时CompletableFuture已成功完成 我有这门课 public class MyClassImplementRunner implements Runnable private final String p
  • 通过参数对函数调用进行反跳

    David Walsh 拥有出色的去抖动实现here https davidwalsh name javascript debounce function Returns a function that as long as it cont
  • Firebase:观察 childAdded 返回现有/旧记录?

    我有一个查询 用 swift 编写 FIRDatabase database reference withPath ORDERS PATH lId child orders observe childAdded with firebaseS
  • Bash sqlite3 行 |如何转换为JSON格式

    我想将数据库中的 sqlite 数据转换为 JSON 格式 我想使用这个语法 sqlite3 linemembers db 从成员LIMIT 3中选择 gt members txt OUTPUT id 1 fname Leif gname
  • TensorFlow 图像分类

    我对 TensorFlow 很陌生 我正在做图像分类使用我自己的训练数据库 然而 在我训练了自己的数据集之后 我不知道如何对输入图像进行分类 这是我的代码准备我自己的数据集 filenames 01 jpg 02 jpg 03 jpg 04
  • 下载极大文件时连接关闭

    我们有一个提供文件的网络服务 最近 我们遇到一个非常大的文件 超过 2 GB 无法复制到缓冲区中 我修改了代码以使用HttpCompletionOptions ResponseHeadersRead不使用缓冲区并直接复制到流 然而 大多数时
  • 如何防止部分视图中的脚本多次加载并在同一页面中多次使用部分时导致错误

    在 ASP NET MVC 中 我创建了一个局部视图 该视图在同一页面上呈现两次 我的问题是JavaScript 被包含的次数与分部视图的次数一样多JavaScript 不喜欢重新定义类 我的问题是 如何将 JavaScript 包含在部分
  • Page_ClientValidate() 问题

    function Subscribe if typeof Page ClientValidate function Page ClientValidate if Page IsValid do something CheckUser 该脚本
  • django 管理操作而不选择对象

    是否可以为 django 管理员创建一个自定义管理操作 而不需要选择某些对象来运行它 如果您尝试在不选择对象的情况下运行操作 您会收到以下消息 Items must be selected in order to perform actio
  • tsc 未被识别为内部或外部命令

    我从 VSCode 0 10 6 更新到 0 10 8 并第一次尝试使用 Typescript 不幸的是 当我告诉 VSCode 构建时 我收到错误 tsc 不被识别为内部或外部命令 以下是相关详情 I created a fresh He
  • 如何采用按单独列排序的 DISTINCT ON 子查询并使其快速?

    又名 查询和数据与问题非常相似 选择按某列排序且在另一列上不同的行 https stackoverflow com questions 9796078 selecting rows ordered by some column and di