Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何使用PK和值的元组高效地更新postgres?_Sql_Postgresql_Tuples - Fatal编程技术网

Sql 如何使用PK和值的元组高效地更新postgres?

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语句的缓冲区 启动交易 创

我的模式如下,我在数据库中已有约400万篇文章需要更新。我正在添加一个指向文本位置的整数

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;