postgresql UPDATE 查询永远占用 300 万行

时间:2021-02-22 11:45:43

标签: sql postgresql sql-update database-performance

这是表架构:

CREATE TABLE public.page_by_category
(
    id integer NOT NULL DEFAULT nextval('page_by_category_id_seq'::regclass),
    page_id bigint NOT NULL,
    category_id bigint NOT NULL,
    weight integer NOT NULL,
    CONSTRAINT id_pk PRIMARY KEY (id),
    CONSTRAINT category_id_fkey FOREIGN KEY (category_id)
    CONSTRAINT page_id_fkey FOREIGN KEY (page_id)
)

这是一个耗时较长的查询:UPDATE page_by_category SET weight=0 在 3m 行上。

查看 pg_stat_activity 这是结果:

30366   "2 days 18:32:12.141453"    "user"  "UPDATE page_by_category SET weight=0"

如何检查查询是否卡住?因为没有 IO,CPU 大量使用......在我的 Centos 上,我正在使用 top,iotop 来查看是否使用了 cpu 或磁盘,但仅使用 5% 以上......

PostgreSQL 版本:""PostgreSQL 10.7 on x86_64-pc-linux-gnu"

2 个答案:

答案 0 :(得分:1)

这应该不会花费太多时间。杀死进程并再次执行查询并检查它是否再次卡住。

SELECT pg_cancel_backend(<pid of the process>)

如果您不知道pid,那么您可以尝试以下查询:

SELECT * FROM pg_stat_activity WHERE state = 'active';

然后找到你要杀死的进程。

如果进程仍然存在,则尝试:

SELECT pg_terminate_backend(<pid of the process>)

(如果可能,在终止查询后重新启动DB,然后重试。)

答案 1 :(得分:1)

由于您的挂起更新的进程 ID 是 30366,您应该查找持有阻塞语句的锁的打开事务:

SELECT pg_blocking_pids(30366);

找出这些连接有什么问题,以及为什么它们持有锁这么长时间。

要杀死他们,请运行

SELECT pg_terminate_backend(?????);

其中 ????? 是通过上述查询找到的阻塞进程 ID 之一。

如果不是锁阻止了您的查询,则以下可能性仍然存在:

  • 您的存储速度非常慢

  • 你有昂贵的行级触发器

  • 你有很多索引

相关问题