postgresql UPDATE 查询永远占用 300 万行
postgresql UPDATE query taking forever with 3m rows
这是 table 架构:
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 on 3m rows.
查看 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”
这应该不会花费太多时间。杀掉进程,重新执行查询,看是否又卡了。
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,然后重试。)
由于您的挂起更新的进程 ID 是 30366,您应该查找持有阻止语句的锁的打开事务:
SELECT pg_blocking_pids(30366);
弄清楚这些连接有什么问题以及为什么它们持有锁这么长时间。
杀了他们,运行
SELECT pg_terminate_backend(?????);
其中 ?????
是通过上述查询找到的阻塞进程 ID 之一。
如果它不是阻止您查询的锁,则仍然存在以下可能性:
您的存储速度非常慢
你有昂贵的行级触发器
你有很多索引
这是 table 架构:
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 on 3m rows.
查看 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”
这应该不会花费太多时间。杀掉进程,重新执行查询,看是否又卡了。
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,然后重试。)
由于您的挂起更新的进程 ID 是 30366,您应该查找持有阻止语句的锁的打开事务:
SELECT pg_blocking_pids(30366);
弄清楚这些连接有什么问题以及为什么它们持有锁这么长时间。
杀了他们,运行
SELECT pg_terminate_backend(?????);
其中 ?????
是通过上述查询找到的阻塞进程 ID 之一。
如果它不是阻止您查询的锁,则仍然存在以下可能性:
您的存储速度非常慢
你有昂贵的行级触发器
你有很多索引