【问题标题】:mysql NOT IN QUERY optimizemysql NOT IN QUERY 优化
【发布时间】:2011-05-25 05:54:52
【问题描述】:

我有两个表命名为:

  1. table_product
  2. table_user_ownned_auction

table_product

specific_product_id      astatus  ... 
(primary_key,autoinc)
--------------------------------------
1                        APAST    ...
2                        ALIVE    ...
3                        ALIVE    ...
4                        APAST    ... 
5                        APAST    ...

table_user_ownned_auction

own_id     specific_product_id   details   
----------------------------------------
1                  1               XXXX
2                  5               XXXX

我需要选择atatus = APAST,而不是在表 2 中。
这意味着,在上述结构表 1 中有 3 个 APAST 状态(1、4、5)。但在表 2 中,specific_product_id (1,5) 仅存储,所以我需要选择 specific_product_id = 4

我使用了这个查询

  SELECT * 
    FROM table_product 
   WHERE astatus = 'APAST' 
     AND specific_product_id NOT IN (SELECT specific_product_id 
                                       FROM table_user_ownned_auction )

...需要这么长时间:

查询耗时 115.1039 秒

...执行。

解释计划

我怎样才能优化它或任何其他方式来选择我想要的?

【问题讨论】:

    标签: mysql sql query-optimization


    【解决方案1】:

    使用NOT EXISTS

    SELECT p.* 
      FROM TABLE_PRODUCT p
     WHERE p.astatus = 'APAST' 
       AND NOT EXISTS (SELECT NULL
                         FROM TABLE_USER_OWNED_AUCTION uoa
                        WHERE uoa.specific_product_id = p.specific_product_id)
    

    使用LEFT JOIN/IS NULL

       SELECT p.* 
         FROM TABLE_PRODUCT p
    LEFT JOIN TABLE_USER_OWNED_AUCTION uoa ON uoa.specific_product_id = p.specific_product_id
        WHERE p.astatus = 'APAST' 
          AND uoa.own_id IS NULL
    

    说明

    最佳查询可以通过两个表之间比较的列是否可为空来确定(即:如果任一表中的specific_product_id 的值可以是NULL)。

    附录

    确定最佳查询后,请至少查看creating indexes (possibly covering indexes)

    • specific_product_id
    • TABLE_PRODUCT.astatus

    【讨论】:

    • 我喜欢你的解决方案。我正在学习mysql。您能否解释一下当 uoa.specific_product_id != p.specific_product_id 时在 NOT EXISTS(..) 的子查询中将选择什么
    • @Sandeep: NOT 执行反转,将uoa.specific_product_id = p.specific_product_id 更改为uoa.specific_product_id != p.specific_product_id
    • 附录一有错别字 -> 一次。
    • 我阅读了您引用的article,似乎LEFT JOIN/IS NULLNOT IN 之间没有性能差异。因此,您可以得出结论,您可以始终使用 NOT IN 并且您始终被覆盖。引用文章中比较两者的引述:“算法实际上是相同的,并且查询在同一时间完成。”
    【解决方案2】:

    尝试在table_user_ownned_auction 表上添加索引:

    ALTER TABLE table_user_ownned_auction ADD KEY(specific_product_id)
    

    另外,尝试使用non-exists 加入:

    SELECT p.*
    FROM table_product p
        LEFT JOIN table_user_ownned_auction l
          ON p.specific_product_id = l.specific_product_id
    WHERE p.astatus = 'APAST' 
        AND l.specific_product_id IS NULL
    

    【讨论】:

    • @gowri: 那也可能是因为查询计划被缓存了
    • 使用准确的字段名而不是SELECT *
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 2012-02-08
    相关资源
    最近更新 更多