0

我的 SCHEMA 如下,我在数据库中有大约 400 万个现有帖子需要更新。我正在添加一个指向文本位置的整数。

CREATE TABLE app_post (
id integer NOT NULL,
text_location integer,
title character varying(140)
);

我想用代表(id,text_location)的长(1000-5000)元组列表更新现有记录:

[(1, 123), (2,3), (9, 10)....]

最有效的方法是什么?

4

1 回答 1

1

如果您使用 phyton 动态生成值,您可以:

  1. 创建一个包含单个INSERT语句的缓冲区
  2. 开始交易
  3. INSERT创建一个临时表并在缓冲区中执行语句
  4. 执行一个UPDATE ... FROM
  5. 提交事务,丢弃临时表。

UPDATE语句将如下所示(假设有一个new_values包含您需要更新的新值的表):

UPDATE app_post AS a SET text_location = n.text_location 
    FROM new_values AS n WHERE a.id = n.id

不要忘记将列定义idPRIMARY KEY或在它们上创建索引。


编辑:由于您遇到的性能非常慢,另一种解决方法可能是重新创建整个表。以下想法假设您没有FOREIGN KEY对表应用任何约束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;

如果有任何FOREIGN KEY约束,您应该注意它们,在 TRUNCATINGapp_post表之前删除它们,并在重新填充表后重新创建它们。

于 2013-09-12T14:59:14.307 回答