当前位置: 首页 > 知识库问答 >
问题:

更新+插入比upsert好?

贺俊杰
2023-03-14

useridpoints都属于int类型或任何其他数字数据类型。userid是我的PK。
现在,我希望在表中执行更新查询,如果该行不存在,我希望插入该行。如果用户已经存在,我希望将点数增加1,否则插入用户ID,点数默认为1。

我知道我可以这样做:

INSERT INTO table(userid, points) VALUES(123, 1)
ON conflict (userid)
DO UPDATE
SET points = table.points + 1 
where table.userid = 123;

但是,在我的情况下,更新操作比插入新行更频繁。假设每天有5000个查询,其中大约4500行是对现有行的update操作。做相反的upsert将是更有利的,因为冲突将减少到500次,而不是4500次。我想先尝试update,如果返回update0,我想执行insert

import asyncio
import asyncpg

async def run():
    conn = await asyncpg.connect(user='user', password='password',
                                 database='database')

    output = await conn.execute("UPDATE table set points = points + 1 where userid = $1", 123)

    if output == "UPDATE 0":
        await conn.execute("INSERT INTO table(userid, points) values($1, $2)", 123, 0)

    await conn.close()

loop = asyncio.get_event_loop()
loop.run_until_complete(run())
    null

共有1个答案

凌炜
2023-03-14

您建议的代码存在争用条件:有人可能会在updateinsert之间插入一行,从而使两者都失败。唯一安全的技术是一个无休止的循环,它尝试两个语句,直到其中一个成功。

由于每个语句都需要客户机-服务器往返,我怀疑您的代码是否会比insert...ON conflict执行得更好。

与其毫无根据地假设insert...ON conflickupdate慢得多,不如对这两个解决方案进行基准测试。

 类似资料:
  • 问题内容: MySQL有这样的东西: 据我所知,SQLite中不存在此功能,我想知道的是,是否有任何方法可以实现相同的效果而不必执行两个查询。另外,如果这不可能,那么您更喜欢什么: SELECT +(插入或更新) 或 UPDATE( 如果UPDATE失败,则 + INSERT ) 问题答案: 因为3.24.0 SQLite还支持upsert ,所以现在您可以简单地编写以下内容

  • 问题内容: 在Slick 3.0中执行批量insertOrUpdate的正确方法是什么? 我正在使用适当的查询的MySQL MySQL批量插入或更新 这是我当前的代码,它很慢:-( 我正在寻找的是等价的 问题答案: 您可以通过多种方法使此代码更快(每个代码都 应该 比前面的代码更快,但是它的习惯用法越来越少): 运行而不是if on slick-pg 0.16.1+ 一次运行所有DBIO事件,而不

  • 问题内容: UPSERT操作会更新表或在表中插入一行,这取决于表是否已经有与数据匹配的行: 由于Oracle没有特定的UPSERT语句,执行此操作的最佳方法是什么? 问题答案: MERGE(“老式方式”)的替代方法:

  • 但现在我也需要知道: 插入了多少行 由于现有而更新了多少行 由于约束无法插入多少行 如果最后一行没有遵守约束,那么以前插入/更新的行是否会保留在数据库中?

  • 问题内容: 我已经查看了网站上的一些问题,但还没有弄清楚我在做什么错。我有一些这样的代码: 我不确定在中间应该做什么以使其正确更新数据库。我已经尝试了很多东西,但是无法撤消以找出所有我尝试过的东西。我一整夜都花了时间,我希望它能正常工作。 这几乎是我想要的,我想知道是否有任何方法可以在条件部分 我会继续玩弄它。 问题答案: 这正是我想要的,只有一行。:D完美!

  • 问题内容: 我有这样的UPSERT操作: 是一个复合主键,与“ people”表相比,“ people_update”表包含其他行和已更改的行。 我的问题是:有没有办法将查询的插入行和更新行作为返回行? 编辑:我通过添加一个子句中途解决了问题,但我也想在我的返回值中获取旧值。 问题答案: 如果将布尔更新的列添加到表中: 那么您可以通过在子句中进行设置来标识更新的行: 例如, 产量 该列显示和行已更