如何在没有重复的情况下进行多个并发质量插入?

时间:2016-01-05 21:20:18

标签: sql postgresql

假设我有4个进程,每个进程都会同时将title, url (unique)的1000条记录插入到blog_posts表中。部分记录将包含重复的url

即使我在插入之前检查记录是否存在,由于进程之间的竞争条件,在每个进程的事务中插入也会失败。每个过程单个质量插入也会失败。我如何使用Postgres快速

我正在考虑将每个进程的记录排队到Redis或其他东西并从那里大量插入它们以防止竞争条件,但我可能还有更好的方法。

2 个答案:

答案 0 :(得分:1)

我升级到Postgres v9.5并使用带有ON CONFLICT DO NOTHING的大量插入,这给了我速度和避免重复的能力。

答案 1 :(得分:0)

我建议的一个可能的解决方案 - 使用临时表,1表示重复数据,2表示过滤它(尽管在某些情况下可能不起作用)。

它也有点冗长,但所有陈述都相当简单,并且很容易将其精确调整到你想要的。

这是一个假设的例子。在这种情况下,我假设我不会操作重复 - 我只想要uniques(基于URL)。我尝试评论步骤,以便更容易看到如何根据需要调整逻辑。

设置临时表并使用任何数据填充它。

--
-- Create temp table, which will store all data, including duplicates.
--
-- DROP TABLE IF EXISTS abc_with_dupes;
--

CREATE TEMP TABLE IF NOT EXISTS abc_with_dupes (
    url   text NOT NULL,
    title text NOT NULL
);

--
-- Create temp table, that will be closer to desired result, with constraints.
--
-- DROP TABLE IF EXISTS abc;
--

CREATE TEMP TABLE IF NOT EXISTS abc (
    url   text NOT NULL,
    title text NOT NULL,
    CONSTRAINT abc_pkey PRIMARY KEY (url)
);

--
-- Sample Data, into temp
--

INSERT INTO abc_with_dupes (url, title) VALUES
('http://example.com', 'a'),
('http://example.com', 'b'),
('http://example.ca' , 'c'),
('http://example.us' , 'd'),
('http://example.ru' , 'e');

仅将唯一记录迁移到abc临时表。逻辑将改变取决于重复需要做什么,在这种情况下,简单地忽略。

INSERT INTO abc (url, title) (
    SELECT X.url, T.title FROM (
        SELECT
            url
        FROM abc_with_dupes
        GROUP BY url
        HAVING(COUNT(*)) = 1
    ) AS X
    JOIN abc_with_dupes T USING(url)
);

并检查结果:

--
-- Quick check: Records that ended up under abc temp table - unique.
--
-- ('http://example.ca' , 'c')
-- ('http://example.us' , 'd')
-- ('http://example.ru' , 'e')
-- 

SELECT * FROM abc;

--
-- Quick check: Records that have duplicate and didn't make to abc temp table
-- 
-- ('http://example.com', 'a')
-- ('http://example.com', 'b')
--

SELECT T.title, X.url FROM (
    SELECT
        url
    FROM abc_with_dupes
    GROUP BY url
    HAVING(COUNT(*)) > 1
) AS X
JOIN abc_with_dupes T USING(url)

希望这会在某种程度上有所帮助。