postgresql - 获取过去 24 小时内未更新的行
问题描述
我有一个大表(40+ 百万条记录),其结构如下:
CREATE TABLE collected_data(
id TEXT NOT NULL,
status TEXT NOT NULL,
PRIMARY KEY(id, status),
blob JSONB,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
我需要获取所有(或至少 100,000 条)updated_at
超过 24 小时、具有某种状态且具有不为空的 blob 的记录。
所以查询变为:
SELECT
id
FROM
collected_data
WHERE
status = 'waiting'
AND blob IS NOT NULL
AND updated_at < NOW() - '24 hours'::interval
LIMIT 100000;
这导致执行计划如下:
Limit (cost=0.00..234040.07 rows=100000 width=12)
-> Seq Scan on collected_data (cost=0.00..59236150.00 rows=25310265 width=12)
" Filter: ((blob IS NOT NULL) AND (type = 'waiting'::text) AND (updated_at >= (now() - '24:00:00'::interval)))"
它几乎总是会导致全表扫描,这意味着某些查询非常慢。
我曾尝试创建类似的索引,CREATE INDEX idx_special ON collected_data(status, updated_at);
但没有帮助。
有什么办法可以让这个查询更快吗?
解决方案
计划者认为 25,310,265 行将满足您的条件,因此它认为通过 seq 扫描仅获取 100,000 行然后提前停止会被宠坏。如果真的没有那么多,或者有那么多但它们都聚集在表格的错误部分,那么这实际上不会那么快。如果在选择了其中的 100,000 个后,您接下来要做的是以不再符合标准的方式更新它们,则尤其可能出现这种情况。因为那时你必须不断地走过那些曾经有资格的人的积累残余物,才能找到下一批。
您可以通过在查询中添加“order by updated_at”来鼓励它使用索引。您还可以通过创建部分索引CREATE INDEX ON collected_data(status, updated_at) where blob is not null
或CREATE INDEX ON collected_data(updated_at) where status='waiting' and blob is not null
.
推荐阅读
- assembly - int 16h/ah=1 即使在用户按下另一个键后也重复给出相同的按键
- angular - 根据值从Angular中的firebase检索数据
- python - Yocto:没有提供 python-db-2.7.16-r1.cortexa7t2hf-neon 所需的 python-bsddb
- html - 使用 VBA excel 在 iFrame 中单击下拉选项
- python-3.x - 如何使用来自多个数据库表的列在 python 中创建数据框
- java - 如何在第一个列表中按另一个列表对一个列表进行排序?
- docker - Docker 运行错误:“无法执行,因为找不到指定的命令或文件”
- google-app-maker - Google AppMaker 如何定义页面级变量
- laravel - 在验证之前运行方法之后的 Laravel 验证器
- google-apps-script - 在 Google 电子表格中获取所有开发者元数据