【问题标题】:Efficient way of phrasing multiple tuple pair WHERE conditions in SQL statement在 SQL 语句中表达多个元组对 WHERE 条件的有效方法
【发布时间】:2010-08-17 05:40:41
【问题描述】:

我想执行一个在逻辑上等同于以下内容的 SQL 查询:

DELETE FROM pond_pairs
WHERE
  ((pond1 = 12) AND (pond2 = 233)) OR
  ((pond1 = 12) AND (pond2 = 234)) OR
  ((pond1 = 12) AND (pond2 = 8)) OR
  ((pond1 = 13) AND (pond2 = 6547)) OR
  ((pond1 = 13879) AND (pond2 = 6))

我会有数十万个pond1-pond2 对。我在(pond1, pond2) 上有一个索引。

我有限的 SQL 知识想出了几种方法:

  1. 按原样运行整个查询。
  2. 使用n WHERE 条件将查询分批成更小的查询
  3. pond1-pond2 对保存到新表中,并在WHERE 子句中进行子查询以识别
  4. 将标识要删除的行的python逻辑转换为存储过程。请注意,我不熟悉编程存储过程,因此这可能涉及陡峭的学习曲线。

如果相关,我正在使用 postgres。

【问题讨论】:

    标签: python sql optimization postgresql


    【解决方案1】:

    对于要在单个 DELETE 中删除的大量 pool1-pond2 对,我将创建临时表并在此表上连接。

    -- Create the temp table:
    CREATE TEMP TABLE foo AS SELECT * FROM (VALUES(1,2), (1,3)) AS sub (pond1, pond2);
    
    -- Delete
    DELETE FROM bar 
    USING  
      foo -- the joined table
    WHERE 
      bar.pond1= foo.pond1 
    AND 
      bar.pond2 = foo.pond2;
    

    【讨论】:

    • 用对填充 TEMP TABLE 是与原始 DELETE 问题相同的问题,但是(除非这些对已经在数据库中的某个地方)。
    • 不,不是,您可以使用 COPY 来填充临时表。这比将数据放入临时表的任何其他选项都快得多。我只是举了一个很简单的例子,但是思路是一样的。
    • 我明白了。 'receive_stmt = destination.prepare("COPY loading_table FROM STDIN")' 是将这些数字放入表中的好方法。
    【解决方案2】:

    我会做 3.(使用 JOIN 而不是子查询)并测量 DELETE 查询的时间(不创建表和插入)。这是一个很好的起点,因为 JOINing 是非常常见且经过优化的过程,所以届时将很难被击败。然后您可以将该时间与您当前的方法进行比较。

    您也可以尝试以下方法:

    1. 按与索引相同的方式对对进行排序。
    2. 使用方法 2. 从您的描述中删除(可能在单个事务中)。

    在删除前排序将提供更好的索引读取性能,因为硬盘缓存工作的机会更大。

    【讨论】:

    • 是的,你在 Frank Heikens 的回答中有例子。
    • 那个 USING 子句很简洁。但他仍然需要将这些对发送到数据库中(除非它们已经在某个地方)。
    • 我并不是说这是最终解决方案。临时表删除是很好的参考点,因为更快地删除记录将非常困难。因此,如果其他命题之一具有相似的速度,那将是不错的选择。
    【解决方案3】:

    对于数十万对,您不能执行 1(按原样运行查询),因为 SQL 语句会太长。

    如果您的表中已有对,则 3 很好。如果没有,您需要先插入它们。如果您以后不需要它们,您也可以运行相同数量的 DELETE 语句而不是 INSERT 语句。

    循环中的准备好的语句怎么样,可能是批处理的(如果 Python 支持的话)

    1. 开始交易
    2. 准备语句“DELETE FROM pond_pairs WHERE ((pond1 = ?) AND (pond2 = ?))”
    3. 循环遍历您的数据(在 Python 中),并使用一对(或添加到批处理)运行语句
    4. 提交

    这些对来自哪里?如果您可以编写 SELECT 语句来识别它们,则可以将此条件移动到删除的 WHERE 子句中。

    DELETE FROM pond_pairs WHERE (pond1, ponds) in (SELECT pond1, pond2 FROM ......  )
    

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2013-03-08
      • 1970-01-01
      • 2012-02-23
      相关资源
      最近更新 更多