最快检查PostgreSQL中是否存在行

Val*_*zub 150 sql postgresql

我有一堆行需要插入到表中,但这些插入总是分批完成.所以我想检查表中是否存在批处理中的单行,因为我知道它们都已插入.

所以它不是主键检查,但不应该太重要.我想只检查单行,所以count(*)可能不好,所以它就像exists我猜的那样.

但是因为我对PostgreSQL相当新,所以我宁愿问那些知道的人.

我的批处理包含具有以下结构的行:

userid | rightid | remaining_count
Run Code Online (Sandbox Code Playgroud)

因此,如果表包含任何提供的行,userid则意味着它们都存在于那里.

Mik*_*keM 280

使用EXISTS关键字返回TRUE/FALSE:

select exists(select 1 from contact where id=12)
Run Code Online (Sandbox Code Playgroud)

  • 对此进行扩展,您可以命名返回的列以便于参考.例如`select exists(从id = 12的联系人中选择1)AS"存在"` (14认同)
  • 这样更好,因为它总是会返回一个值(true或false),而不是有时会返回None(取决于你的编程语言),这可能不会像你期望的那样扩展. (3认同)
  • 我使用这种方法进行了 Seq Scan。我做错了什么? (2认同)
  • @Michael.MI有30万行的DB表,当我使用```exists```或```limit 1```时,我的性能下降很强,因为Postgres使用Seq Scan而不是Index Scan.并且```analyze```没有帮助. (2认同)
  • 此处子查询中的“limit 1”会帮助还是减慢查询速度? (2认同)
  • @maciek,请理解“ id”是主键,因此“ LIMIT 1”将毫无意义,因为只有一个带有该ID的记录 (2认同)
  • @CodeGuru,视情况而定。SERIAL 比 BYTE 大 4 倍。对于每 1MM 的正数,您将比仅使用“exists”多编组 3MB 的数据,而您最终会丢弃这些数据。BIGSERIAL 多出 7MB。此外,根据您的调用代码,仅处理响应中的 bool 可能会更有效,而不是评估是否有记录。如果不了解 OP 案件的具体情况,就无法判断。无论如何,如果我们知道总是得到一个布尔值,那么代码就更容易阅读。 (2认同)
  • @maciek如果您不比较“UNIQUE”(包括“PRIMARY KEY”)列,它会有所帮助。否则,毫无意义。 (2认同)

NPE*_*NPE 33

怎么样简单:

select 1 from tbl where userid = 123 limit 1;
Run Code Online (Sandbox Code Playgroud)

123您要插入的批次的用户标识在哪里.

上述查询将返回空集或单行,具体取决于是否存在具有给定用户标识的记录.

如果结果太慢,你可以考虑创建一个索引tbl.userid.

如果在表中存在批处理中的单行,那么我不必插入我的行,因为我知道它们都已插入.

为了使这一点保持正确,即使您的程序在批处理中被中断,我建议您确保正确管理数据库事务(即整个批处理在单个事务中插入).

  • 有时可能在程序上更容易"从(选择1 ...限制1)中选择计数(\*)",因为它保证始终返回值为count(\*)为0或1的行. (11认同)
  • @Imraan我认为你误解了这个问题.`COUNT`作用于一个最多有1行的嵌套`SELECT`(因为'LIMIT`在子查询中). (2认同)

wil*_*ser 9

INSERT INTO target( userid, rightid, count )
  SELECT userid, rightid, count 
  FROM batch
  WHERE NOT EXISTS (
    SELECT * FROM target t2, batch b2
    WHERE t2.userid = b2.userid
    -- ... other keyfields ...
    )       
    ;
Run Code Online (Sandbox Code Playgroud)

顺便说一句:如果你希望整个批次在重复的情况下失败,那么(给定主键约束)

INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count 
FROM batch
    ;
Run Code Online (Sandbox Code Playgroud)

会做你想做的事:要么成功,要么失败.


Roy*_*yce 5

select true from tablename where condition limit 1;
Run Code Online (Sandbox Code Playgroud)

我相信这是 postgres 用于检查外键的查询。

对于您的情况,您也可以一次性执行此操作:

insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1);
Run Code Online (Sandbox Code Playgroud)


fra*_*ncs 5

如果您考虑性能,也许您可​​以在函数中使用“PERFORM”,如下所示:

 PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1;
  IF FOUND THEN
      RAISE NOTICE ' found record id=%', i;  
  ELSE
      RAISE NOTICE ' not found record id=%', i;  
 END IF;
Run Code Online (Sandbox Code Playgroud)

  • 那是 pl/pgsql,而不是 SQL,因此如果尝试将其作为 SQL 运行,则会出现“PERFORM”语法错误 (2认同)