MySQL NOT IN 查询响应时间过长
MySQL NOT IN query taking too long to respond
查询响应时间太长,大约需要 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
table有
- consumer_id varchar(12)
- active_flag varchar(6)
- 频率 varchar (2)
- 130000 行带有 where 子句
- 总行数 160000
- consumer_id
上的唯一索引
- active_flag
上的索引
transaction
table有
- consumer_id varchar(12)
- active_flag varchar(6)
- status 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
解释一下return
SQL QUERY EXPLAIN
希望对您有所帮助。
提前致谢。
更新 1
消费者和交易是一对多的关系
所以 consumer_id 将在每个周期重复。
使用左连接你会得到 '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' )
使用右连接或内连接以获得您想要的结果。
为了加快查询速度,您应该为 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'
我不确定您的数据是什么样的,所以我不确定以下是否有效,但您可能想尝试一下查询的基本逻辑,因为您想要做的事情应该可以在不使用的情况下实现子查询。
作为一般规则,您总是希望远离使用子查询,因为它们效率极低。
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 table。
查询响应时间太长,大约需要 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
table有
- consumer_id varchar(12)
- active_flag varchar(6)
- 频率 varchar (2)
- 130000 行带有 where 子句
- 总行数 160000
- consumer_id 上的唯一索引
- active_flag 上的索引
transaction
table有
- consumer_id varchar(12)
- active_flag varchar(6)
- status 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
解释一下return SQL QUERY EXPLAIN
希望对您有所帮助。 提前致谢。
更新 1
消费者和交易是一对多的关系 所以 consumer_id 将在每个周期重复。
使用左连接你会得到 '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' )
使用右连接或内连接以获得您想要的结果。 为了加快查询速度,您应该为 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'
我不确定您的数据是什么样的,所以我不确定以下是否有效,但您可能想尝试一下查询的基本逻辑,因为您想要做的事情应该可以在不使用的情况下实现子查询。
作为一般规则,您总是希望远离使用子查询,因为它们效率极低。
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 table。