【问题标题】:MySQL NOT IN query taking too long to respondMySQL NOT IN 查询响应时间过长
【发布时间】:2017-07-12 16:50:14
【问题描述】:

查询需要很长时间才能响应 ~ 40 分钟。

`SELECT c.consumer_id FROM consumer c
WHERE  c.active_flag = 'Y'
      AND ( c.frequency = 'Q' )
      AND c.consumer_id NOT IN(
  SELECT consumer_id
  FROM (SELECT s.consumer_id
        FROM transactions s
        WHERE ( s.cycle='2016-Q-2' ) and s.active_flag = 'Y' AND s.status <> 'Door Locked')
    AS subquery)`

我也尝试过同时使用上述查询的 NOT EXISTS 和 LEFT JOIN / IS NULL 版本。

consumer表有

  • consumer_id varchar(12)
  • active_flag varchar(6)
  • 频率 varchar (2)
  • 130000 行带有 where 子句
  • 总行数 160000
  • consumer_id 上的唯一索引
  • active_flag 上的索引

transaction表有

  • consumer_id varchar(12)
  • active_flag varchar(6)
  • 状态 varchar (20)
  • 循环 varchar (13)
  • 108000 行带有 where 子句
  • 总行数 270000
  • consumer_id 状态和周期索引

服务器配置

-16GB 内存 -8 核 Intel(R) Xeon(R) CPU E5-4640 v2 @ 2.20GHz -MySQL 5.6.35

解释退货 SQL QUERY EXPLAIN

我希望这会有所帮助。 提前致谢。

更新 1

消费者和交易是一对多的关系 所以 consumer_id 会在每个周期重复。

【问题讨论】:

  • 能否请您也添加您的 JOIN 查询?

标签: mysql notin


【解决方案1】:

使用左连接,您将获得 'NULL' 值

尝试使用内部连接可能会对您有所帮助

SELECT c.consumer_id FROM consumer c
JOIN 
    (SELECT s.consumer_id as S_ID 
     FROM transactions s
     WHERE (s.cycle='2016-Q-2') and s.active_flag = 'Y' AND s.status <> 
    'Door Locked')
ON s.S_ID <> c.consumer_id
WHERE  c.active_flag = 'Y' AND ( c.frequency = 'Q' )

【讨论】:

    【解决方案2】:

    Inner Join 帮了我大忙

    SELECT DISTINCT c.consumer_id FROM consumer c
    INNER JOIN
        (SELECT DISTINCT consumer_id as sid from transactions where consumer_id not in (
      select consumer_id from transactions
      where cycle = '2016-Q-2' AND active_flag = 'Y' AND status != 'Door Locked'
    )) as s
    ON s.sid = c.consumer_id
    WHERE  c.active_flag = 'Y' AND ( c.frequency = 'Q' )
    

    不确定这是否正确,但现在响应时间已降至约 700 毫秒。

    不知道为什么,但来自上述所有答案的查询响应提供了事务表中可用的所有消费者 ID。

    【讨论】:

      【解决方案3】:

      使用右连接或内连接来获得您想要的结果。 为了加快查询速度,您应该为 WHERE 子句中的所有字段添加索引。祝你好运!

      SELECT DISTINCT c.consumer_id FROM consumer c
      INNER JOIN transactions s
      ON s.cycle != '2016-Q-2' AND s.active_flag != 'Y' AND s.status = 'Door Locked' 
      WHERE  c.active_flag = 'Y'
      AND c.frequency = 'Q'
      

      【讨论】:

        【解决方案4】:

        我不确定您的数据是什么样的,因此我不确定以下内容是否有效,但您可能希望使用查询的底层逻辑,因为您想要做的事情应该可以在不使用子查询的情况下实现。

        作为一般规则,您总是希望远离使用子查询,因为它们效率极低。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多