MySQL:WHERE子句中带有NOT IN的从属子查询非常慢
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了MySQL:WHERE子句中带有NOT IN的从属子查询非常慢,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4090字,纯文字阅读大概需要6分钟。
内容图文
我正在使用open Id登录来审核我的应用程序中的用户详细信息.如果用户第一次登录我们认为是注册的OPEN ID.我正在使用此详细信息生成审计登录报告.样本表数据.
+---------+----------+-----------+---------------+
| USER_ID | PROVIDER | OPERATION | TIMESTAMP |
+---------+----------+-----------+---------------+
| 120 | Google | SIGN_UP | 1347296347000 |
| 120 | Google | SIGN_IN | 1347296347000 |
| 121 | Yahoo | SIGN_IN | 1347296347000 |
| 122 | Yahoo | SIGN_IN | 1347296347000 |
| 120 | Google | SIGN_UP | 1347296347000 |
| 120 | FaceBook | SIGN_IN | 1347296347000 |
+---------+----------+-----------+---------------+
在此表中,我想基于提供程序排除已经SIGN_UP ed“SIGN_IN”ed用户计数.
显示创建表
CREATE TABLE `signin_details` (
`USER_ID` int(11) DEFAULT NULL,
`PROVIDER` char(40) DEFAULT NULL,
`OPERATION` char(40) DEFAULT NULL,
`TIMESTAMP` bigint(20) DEFAULT NULL
) ENGINE=InnoDB
我正在使用此查询.
select
count(distinct(USER_ID)) as signin_count,
PROVIDER from signin_details s1
where
s1.USER_ID NOT IN
(
select
USER_ID
from signin_details
where
signin_details.PROVIDER=s1.PROVIDER
and signin_details.OPERATION='SIGN_UP'
and signin_details.TIMESTAMP/1000 BETWEEN UNIX_TIMESTAMP(CURRENT_DATE()-INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000
)
AND OPERATION='SIGN_IN' group by PROVIDER;
解释输出:
+----+--------------------+----------------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------------+------+---------------+------+---------+------+------+-----------------------------+
| 1 | PRIMARY | s1 | ALL | NULL | NULL | NULL | NULL | 6 | Using where; Using filesort |
| 2 | DEPENDENT SUBQUERY | signin_details | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
+----+--------------------+----------------+------+---------------+------+---------+------+------+-----------------------------+
查询输出:
+--------------+----------+
| signin_count | PROVIDER |
+--------------+----------+
| 1 | FaceBook |
| 2 | Yahoo |
+--------------+----------+
执行20万行需要40多分钟.
我的假设是它将检查每一行的从属子查询输出的总数.
我对此查询的假设.
A -> Dependant Outputs (B,C,D) .
A check with B
A check with C
A check with D
如果依赖查询输出较大,则执行需要很长时间.如何改进此查询?
解决方法:
如果你使用MySQL,你必须知道子查询执行得很慢.
IN很慢……
EXISTS通常比IN更快
JOIN主要是做这样事情的最快方式.
SELECT DISTINCT
s1.PROVIDER,
COUNT(DISTINCT s1.USER_ID)
FROM
signin_details s1
LEFT JOIN
(
SELECT DISTINCT
USER_ID, PROVIDER
FROM
signin_details
WHERE
signin_details.OPERATION='SIGN_UP'
AND
signin_details.TIMESTAMP
BETWEEN
UNIX_TIMESTAMP(CURRENT_DATE()-INTERVAL 1 DAY) * 1000
AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000
) AS t USING (USER_ID, PROVIDER)
WHERE
t.USER_ID IS NULL
AND OPERATION='SIGN_IN'
GROUP BY s1.PROVIDER
http://sqlfiddle.com/#!2/122ac/12
注意:如果您想知道sqlfiddle结果,请考虑查询中的UNIX_TIMESTAMP.
结果:
| PROVIDER | COUNT(DISTINCT S1.USER_ID) |
-----------------------------------------
| FaceBook | 1 |
| Yahoo | 2 |
MySQL和INTERSECT的故事.您将获得您不想计算的所有USER_ID和PROVIDER组合.然后LEFT加入他们的数据.现在,您想要计算的所有行都没有来自LEFT JOIN的值.你通过t.USER_ID得到它们是空的.
输入:
| rn° | USER_ID | PROVIDER | OPERATION | TIMESTAMP |
-------------------------------------------------------
| 1 | 120 | Google | SIGN_UP | 1347296347000 | -
| 2 | 120 | Google | SIGN_IN | 1347296347000 | - (see rn° 1)
| 3 | 121 | Yahoo | SIGN_IN | 1347296347000 | Y
| 4 | 122 | Yahoo | SIGN_IN | 1347296347000 | Y
| 5 | 120 | Google | SIGN_UP | 1347296347000 | -
| 6 | 120 | FaceBook | SIGN_IN | 1347296347000 | F
| 7 | 119 | FaceBook | SIGN_IN | 1347296347000 | - (see rn° 8)
| 8 | 119 | FaceBook | SIGN_UP | 1347296347000 | -
内容总结
以上是互联网集市为您收集整理的MySQL:WHERE子句中带有NOT IN的从属子查询非常慢全部内容,希望文章能够帮你解决MySQL:WHERE子句中带有NOT IN的从属子查询非常慢所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。