Sql 如何使用PK和值的元组高效地更新postgres?
我的模式如下,我在数据库中已有约400万篇文章需要更新。我正在添加一个指向文本位置的整数Sql 如何使用PK和值的元组高效地更新postgres?,sql,postgresql,tuples,Sql,Postgresql,Tuples,我的模式如下,我在数据库中已有约400万篇文章需要更新。我正在添加一个指向文本位置的整数 CREATE TABLE app_post ( id integer NOT NULL, text_location integer, title character varying(140) ); 我想用一长串(1000-5000)元组更新现有记录,元组表示(id,text\u位置): 最有效的方法是什么?如果您正在使用phyton动态生成值,您可以: 创建包含单个INSERT语句的缓冲区 启动交易 创
CREATE TABLE app_post (
id integer NOT NULL,
text_location integer,
title character varying(140)
);
我想用一长串(1000-5000)元组更新现有记录,元组表示(id,text\u位置):
最有效的方法是什么?如果您正在使用phyton动态生成值,您可以:
INSERT
语句的缓冲区INSERT
语句更新。。。从
UPDATE
语句如下所示(假设有一个表new\u values
包含需要更新的新值):
不要忘记将列id
定义为主键,或在其上创建索引
编辑:由于您的性能非常慢,另一种解决方法是重新创建整个表。以下想法假设您没有对
app_post
表应用任何外键
约束,正如您在初始帖子中所示
-- Begin the Transaction
BEGIN;
-- Create a temporary table to hold the new values
CREATE TEMPORARY TABLE temp_update_values (
id integer PRIMARY KEY,
text_location integer
) ON COMMIT DROP;
-- Populate it
INSERT INTO temp_update_values (id, text_location) VALUES (1, 123), (2, 456) /* ... #5000 total */ ;
-- Create a temporary table merging the existing "app_post" and "temp_update_values"
CREATE TEMPORARY TABLE temp_new_app_post ON COMMIT DROP AS
SELECT a.id, COALESCE(n.text_location, a.text_location) AS text_location, a.title
FROM app_post AS a LEFT JOIN temp_update_values AS n ON a.id = n.id;
-- Empty the existing "app_post"
TRUNCATE TABLE app_post;
-- Repopulate "app_post" table
INSERT INTO app_post (id, text_location, title)
SELECT id, text_location, title FROM temp_new_app_post;
-- Commit the Transaction
COMMIT;
如果存在任何
外键
约束,您应该处理它们,在截断app_post
表之前删除它们,并在重新填充后重新创建它们。您有存储这些元组的表吗,还是将它们放在单独的文件中?它们是使用python动态生成的,但是我可以将它们写入一个文件并从那里进行处理。我认为最有效的方法是将这些值存储在一个单独的表中(即使是临时表也可以),如果您在id
列上创建一些适当的索引(如果您像id integer主键那样定义它们,则索引无论如何都是隐式的),从
查询执行更新将非常快。我正在回答以显示可能的解决方案。谢谢!我需要使用“开始”来启动事务吗?无论我以何种方式执行,这可能都很慢,但从新的\u值到应用程序\u post运行更新需要188秒(我有400万个帖子要浏览,所以看了差不多一周)。我运行了上面的代码,下面是解释分析:关于事务,是的,您必须在创建临时表之前使用BEGIN
,在更新之后使用COMMIT
。关于速度,时间肯定太多了。您在app_post
表上没有任何触发器?最快的方法是创建一个新表,这可能很简单,也可能很棘手,这取决于你实际的外键
。我会更新答案。我实际上有一个外键:是否有任何外键
指向应用程序帖子
表?在这种情况下,你必须处理它们,只需在众多方法中选择一种,下面是关于这一点的讨论s主题:
UPDATE app_post AS a SET text_location = n.text_location
FROM new_values AS n WHERE a.id = n.id
-- Begin the Transaction
BEGIN;
-- Create a temporary table to hold the new values
CREATE TEMPORARY TABLE temp_update_values (
id integer PRIMARY KEY,
text_location integer
) ON COMMIT DROP;
-- Populate it
INSERT INTO temp_update_values (id, text_location) VALUES (1, 123), (2, 456) /* ... #5000 total */ ;
-- Create a temporary table merging the existing "app_post" and "temp_update_values"
CREATE TEMPORARY TABLE temp_new_app_post ON COMMIT DROP AS
SELECT a.id, COALESCE(n.text_location, a.text_location) AS text_location, a.title
FROM app_post AS a LEFT JOIN temp_update_values AS n ON a.id = n.id;
-- Empty the existing "app_post"
TRUNCATE TABLE app_post;
-- Repopulate "app_post" table
INSERT INTO app_post (id, text_location, title)
SELECT id, text_location, title FROM temp_new_app_post;
-- Commit the Transaction
COMMIT;