暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【译】用于批量操作的 Postgres UNNEST 备忘单

原创 剩余价值 2022-05-17
505

原文作者 福布斯林德赛

 ·

原文链接https://dzone.com/articles/postgres-unnest-cheat-sheet-for-bulk-operations


如果您想一次交互数千行,UNNEST 是使 Postgres 查询快速可靠的唯一方法。


Postgres 通常非常快,但如果查询中的参数过多,它可能会变慢(甚至完全失败)。在批量处理数据时,这UNNEST是实现快速、可靠查询的唯一方法。UNNEST这篇文章有用于执行所有类型的批量交易的示例。

本文中的所有示例都假定数据库模式如下所示:

CREATE TABLE users (
  email TEXT NOT NULL PRIMARY KEY,
  favorite_color TEXT NOT NULL
)


一次插入数千条记录

要将多条记录一次性插入 Postgres 表中,最有效的方法是将每一列提供为单独的数组,然后用于UNNEST构造要插入的行。

您可以运行以下查询:

INSERT INTO users (email, favorite_color)
SELECT
  UNNEST(?::TEXT[]),
  UNNEST(?::TEXT[])


使用以下参数:

[
  ["joe@example.com", "ben@example.com", "mary@example.com"],
  ["red", "green", "indigo"]
]


请注意,无论您要插入多少行,您都只传递了 2 个参数。无论您要插入多少行,您都在使用相同的查询文本。这就是使查询如此高效的原因。

结果表如下所示:

电子邮件最喜欢的颜色
joe@example.comred
ben@example.comgreen
mary@example.comindigo

在单个查询中将多条记录更新为不同的值

最强大的用例之一UNNEST是在单个查询中更新多条记录。UPDATE如果您想将它们全部设置为相同的值,则普通语句仅允许您一次更新多个记录,但这种方法更加灵活。

您可以运行以下查询:

UPDATE users
SET
  favorite_color=bulk_query.updated_favorite_color
FROM
  (
    SELECT
      UNNEST(?::TEXT[])
        AS email,
      UNNEST(?::TEXT[])
        AS updated_favorite_color
  ) AS bulk_query
WHERE
  users.email=bulk_query.email


使用以下参数:

[
  ["joe@example.com", "ben@example.com", "mary@example.com"],
  ["purple", "violet", "orange"]
]


结果表将如下所示:

电子邮件最喜欢的颜色
joe@example.compurple
ben@example.comviolet
mary@example.comorange

这不仅让您可以在一个语句中更新所有这些记录,而且参数的数量现在固定为 2,无论您要更新多少行。

一次选择数千种不同的条件

你总是可以通过组合ORand来构建一个非常大的查询AND,但最终,如果你有足够的参数,这可能会开始变得很慢。

您可以运行以下查询:

SELECT * FROM users
WHERE (email, favorite_color) IN (
  SELECT
    UNNEST(?::TEXT[]),
    UNNEST(?::TEXT[])
)


使用以下参数:

[
  ["joe@example.com", "ben@example.com", "mary@example.com"],
  ["purple", "violet", "orange"]
]


它相当于运行:

SELECT * FROM users
WHERE
  (email='joe@example.com' AND favorite_color='purple')
  OR (email='ben@example.com' AND favorite_color='violet')
  OR (email='mary@example.com' AND favorite_color='orange')


在这里使用UNNEST可以让我们保持查询不变,并且只使用 2 个参数,无论我们要添加多少条件。

如果您需要更多控制,另一种方法是使用 INNER JOIN 而不是IN查询的一部分。例如,如果您需要测试不区分大小写,您可以这样做:

SELECT users.* FROM users
INNER JOIN (
  SELECT
    UNNEST(?::TEXT[]) AS email,
    UNNEST(?::TEXT[]) AS favorite_color
) AS unnest_query
ON (LOWER(users.email) = LOWER(unnest_query.email) AND LOWER(user.favorite_color) = LOWER(unnest_query.favorite_color))


一次性删除数千种不同的条件

就像SELECTDELETE如果条件的复杂性变得过于极端,查询可能会变慢。

您可以运行以下查询:

DELETE FROM users
WHERE (email, favorite_color) IN (
  SELECT
    UNNEST(?::TEXT[]),
    UNNEST(?::TEXT[])
)


使用以下参数:

[
  ["joe@example.com", "ben@example.com", "mary@example.com"],
  ["purple", "violet", "orange"]
]


它相当于运行:

DELETE FROM users
WHERE
  (email='joe@example.com' AND favorite_color='purple')
  OR (email='ben@example.com' AND favorite_color='violet')
  OR (email='mary@example.com' AND favorite_color='orange')


就像 with 一样SELECT,在这里使用UNNEST可以让我们保持查询不变,并且只使用 2 个参数,而不管我们要添加多少条件。

如果您使用的是 node.js,则可以执行所有这些操作,而无需使用@database/pg-typedor来记住语法@database/pg-bulk

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论