【问题标题】:What is the size limitation for IN and NOT IN in MySQLMySQL 中 IN 和 NOT IN 的大小限制是多少
【发布时间】:2009-01-17 05:12:44
【问题描述】:

当 IN 或 NOT IN 的条件非常大时,我的应用程序出现内存不足异常。我想知道这样做的限制是什么。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    我遇到了类似的问题,但在我的 IN 子句中只传递了 100 个 3 位 id。当我查看堆栈跟踪时,它实际上切断了 IN 子句中的逗号分隔值。我没有收到错误,我只是没有得到所有结果返回。以前有没有人遇到过这样的问题?如果它相关,我正在使用 symfony 框架......我正在检查它是否是一个推进问题,但只是想要看看会不会是sql

    【讨论】:

    • 是的,同样的问题
    【解决方案2】:

    也许您最好用另一种方式来完成您的查询?

    我建议您将匹配值加载到单列表中,然后将正在查询的列内连接到新表中的单列。

    而不是

    SELECT a, b, c FROM t1 WHERE d in (d1, d2, d3, d4, ...)
    

    建立一个有 1 列的临时表,称之为“dval”

    dval ---- d1 d2 d3
    SELECT a, b, c FROM t1  
    INNER JOIN temptbl ON t1.d = temptbl.dval
    

    【讨论】:

    • 谢谢。我们也正在为该问题计划相同的解决方案。但是,在现有安装中添加新表需要一些额外的验证和时间 - 因此,作为临时解决方法,我们考虑拆分查询。
    • 我不太记得了,但我认为临时表不需要太多的权限,因为它在 tempdb 中暂时发生。但在短期内,我希望循环使用您确定的可接受的 arg 计数。
    • 或者,如果您同时需要它们,您可以对多个语句执行 UNION。
    【解决方案3】:

    我只在条件非常小时(不到 100 行左右)时才使用 IN 和 NOT IN。它在这些场景中表现良好。当条件很大时,我使用 OUTER JOIN,因为查询不必为每个元组查找“IN”条件。您只需检查您希望所有行来自的表。

    对于“IN”,连接条件不为空

    对于“NOT IN”,连接条件为空

    例如

    /* Get purchase orders that have never been rejected */
    SELECT po.*
    FROM PurchaseOrder po LEFT OUTER JOIN 
         (/* Get po's that have been rejected */
         SELECT po.PurchaesOrderID
         FROM PurchaseOrder po INNER JOIN 
             PurchaseOrderStatus pos ON po.PurchaseOrderID = pos.PurchaseOrderID
         WHERE pos.Status = 'REJECTED'
         ) por ON po.PurchaseOrderID = por.PurchaseOrderID
    WHERE por.PurchaseOrderID IS NULL    /* We want NOT IN */
    

    【讨论】:

      【解决方案4】:

      在执行 SQL 查询或数据库设计时必须询问限制是您做错了的一个很好的指标。

      【讨论】:

      • @PhoenixRedeemer 是的,我同意我的方法是错误的。更改整个设计需要一些时间,所以我认为一些解决方法可能会暂时解决问题
      【解决方案5】:

      我使用了包含大量 ID 列表的 IN - 我怀疑内存问题不在查询本身。您如何检索结果?

      此查询,例如来自实时站点:

      SELECT DISTINCT c.id, c.name FROM categories c 
      LEFT JOIN product_categories pc ON c.id = pc.category_id 
      LEFT JOIN products p ON p.id = pc.product_id 
      WHERE p.location_id IN (
      955,891,901,877,736,918,900,836,846,914,771,773,833,
      893,782,742,860,849,850,812,945,775,784,746,1036,863,
      750,763,871,817,749,838,986,794,867,758,923,804,733,
      949,808,837,741,747,954,939,865,857,787,820,783,760,
      911,745,928,818,887,847,978,852
      ) ORDER BY c.name ASC  
      

      我第一次编写代码非常幼稚,一个页面上大约有 10 个这样的查询,并且数据库不会闪烁。

      当然,您可以运行一个包含 100k 值的列表,这完全是另一回事。

      【讨论】:

      • @tobyhede:即使在我们的例子中,查询也适用于少量数据。当计数超过 4K 时,我遇到了这个内存问题。
      【解决方案6】:

      我不知道限制是什么,但我以前也遇到过这个问题。我不得不像这样重写我的查询:

      select * from foo
        where id in (select distinct foo_id from bar where ...)
      

      【讨论】:

        猜你喜欢
        • 2019-03-31
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        • 1970-01-01
        • 2017-12-01
        • 1970-01-01
        • 2012-04-21
        • 1970-01-01
        相关资源
        最近更新 更多