【问题标题】:SQL NOT IN [list of ids] (performance)SQL NOT IN [list of ids](性能)
【发布时间】:2019-08-21 02:54:15
【问题描述】:

我只是想知道列表中 id 的数量是否会影响查询性能。

查询示例:

SELECT * FROM foos WHERE foos.ID NOT IN (2, 4, 5, 6, 7)

(2, 4, 5, 6, 7) 是一个无限长的列表。

多少才算太多(按顺序)?

更新:我之所以问它是因为我有两个数据库。其中一个(只读)是项目的来源,另一个包含由操作员处理的项目。每次当操作员从只读数据库中请求新项目时,我都想排除已处理的项目。

【问题讨论】:

  • 您不应该也标记这个 DB2 吗?到底什么是“无限开槽”?我应该害怕还是兴奋?
  • @AaronBertrand 我知道,对不起,但考虑到标题说 Mysql 但后来添加了每个 RDBMS 标签,我有点烦。
  • 您的问题有点像问“以什么速度倒车危险?”在这种情况下,有很多方法可以满足您的要求,但如果您能提供请求的实际原因,我们可能会更有帮助。
  • “Groove 在列表中”是一个新的 Dee-Lite 粉碎
  • 不能代表其他人,但我会告诉你为什么我投了反对票:(1)你问了一个基本的“这会慢吗?”您可以在比编写问题更短的时间内自行测试的问题。当您遇到实际性能问题时,请发布特定问题。 (2) 您故意标记不当。如果您认为在约 1000 个代表中失去 -8 是不好的,请在 Android 论坛上发布一个 iPhone 问题,看看会发生什么。我保证反应不会是“少女”。供将来参考,请阅读:dba.blogoverflow.com/2012/06/help-us-help-you(特别是“有效标记”)

标签: mysql


【解决方案1】:

是的,列表中的 ID 数量会影响性能。例如,一个网络数据包只有这么大,数据库必须解析所有这些噪音并将其转化为一系列:

WHERE foo.ID <> 2
AND foo.ID <> 4
AND foo.ID <> 5
AND ...

您应该考虑其他方式让您的查询了解此集合。

【讨论】:

    【解决方案2】:

    这是对该查询的古怪重写,可能会执行得更好

    SELECT * FROM foos
    LEFT JOIN
    (
        SELECT 2 id UNION
        SELECT 4    UNION
        SELECT 5    UNION
        SELECT 6    UNION
        SELECT 7
    ) NOT_IDS
    USING (id) WHERE NOT_IDS.id IS NULL;
    

    NOT_IDS 子查询的工作方式如下所示:

    mysql> SELECT * FROM
        -> (
        ->     SELECT 2 id UNION
        ->     SELECT 4    UNION
        ->     SELECT 5    UNION
        ->     SELECT 6    UNION
        ->     SELECT 7
        -> ) NOT_IDS;
    +----+
    | id |
    +----+
    |  2 |
    |  4 |
    |  5 |
    |  6 |
    |  7 |
    +----+
    5 rows in set (0.00 sec)
    
    mysql>
    

    【讨论】:

    • MySQL 对它的翻译与现有查询有什么不同吗?我想令人震惊的部分仍将构建内部UNION,具体取决于列表的来源。但在我的脑海中,这仍然转化为id &lt;&gt; 2 AND id &lt;&gt; 4 AND id &lt;&gt; 5 AND id &lt;&gt; 6 AND id &lt;&gt; 7...
    【解决方案3】:

    只是为了好玩,鉴于您的更新,我将提出不同的策略:

    你可以像这样跨表加入...

    insert into db1.foos (cols) 
      select cols
        from db2.foos src
      left join db1.foos dst
        on src.pk = dst.pk
      where dst.othercolumn is null
    

    我不确定优化器将如何处理这个问题,或者它是否会比你正在做的更快(我猜取决于你的索引策略)。

    【讨论】:

      【解决方案4】:

      数据库在同一台服务器上?如果是,您可以使用左连接进行多数据库查询并获取空值。 (这里是一个例子:Querying multiple databases at once)。否则,您可以创建一个存储过程,用字符串传递 id,然后用正则表达式将它们拆分。我有类似的问题,但在内存数据库和 postgres 数据库中。幸运的是我的情况是(在...)

      【讨论】:

        猜你喜欢
        • 2018-10-18
        • 2012-05-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-05
        • 2022-12-01
        • 2022-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多