mysql NOT IN QUERY 优化

Posted

技术标签:

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

我有两个表命名为:

    table_product 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 秒

...执行。

解释计划

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

【问题讨论】:

【参考方案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)。

如果nullable, NOT IN or NOT EXISTS is the best choice in mysql 如果NOT nullable, `LEFT JOIN/IS NULL is the best choice in MySQL

附录

确定最佳查询后,请至少查看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 *

以上是关于mysql NOT IN QUERY 优化的主要内容,如果未能解决你的问题,请参考以下文章

MySQL教程

MySQL

MySQL

有什么学习MySQL的好教程吗?

MySql 详解

MySQL 5.7 新增默认账号 mysql.session和mysql.sys