这个mysql查询需要5分20秒才能执行
SELECT PROVIDER, COUNT(DISTINCT(NAME)) FROM Test WHERE NAME NOT IN (SELECT NAME
FROM Test WHERE OPERATION = 'SIGN_IN' and Test.CREATED_TIME BETWEEN UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000)
AND Test.CREATED_TIME BETWEEN UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000 AND OPERATION='VALIDATE' GROUP BY PROVIDER;
解释给出以下结果
explain SELECT PROVIDER, COUNT(DISTINCT(NAME)) FROM Test WHERE NAME NOT IN
(SELECT NAME FROM Test WHERE OPERATION = 'SIGN_IN' and Test.CREATED_TIME BETWEEN
UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000) AND Test.CREATED_TIME BETWEEN UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000 AND OPERATION='VALIDATE' GROUP BY PROVIDER;
+----+--------------------+-----------------+----------------+----------------------------------------------------------------------+-------------------------+---------+------+--------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------------+----------------+----------------------------------------------------------------------+-------------------------+---------+------+--------+------------------------------------+
| 1 | PRIMARY | Test | ALL | Test_CTndx,Test_CORndx | NULL | NULL | NULL | 137523 | Using where; Using filesort |
| 2 | DEPENDENT SUBQUERY | Test | index_subquery | Test_NAMEndx,Test_CTndx,Test_CORndx | Test_NAMEndx | 303 | func | 148 | Using where; Full scan on NULL key |
+----+--------------------+-----------------+----------------+----------------------------------------------------------------------+-------------------------+---------+------+--------+------------------------------------+
表中的行数为50,000。
如何优化此功能?
答案 0 :(得分:1)
重写您的查询以将NOT IN
替换为等效的NOT EXISTS
语句应该更快。
例如,尝试这样的事情:
SELECT t1.PROVIDER, COUNT(DISTINCT(t1.NAME))
FROM Test t1
WHERE t1.CREATED_TIME BETWEEN UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000
AND t1.OPERATION='VALIDATE'
and NOT EXISTS (
select null
from test t2
where t2.OPERATION = 'SIGN_IN'
and t2.CREATED_TIME BETWEEN UNIX_TIMESTAMP(CURRENT_DATE() - INTERVAL 1 DAY) * 1000 AND UNIX_TIMESTAMP(CURRENT_DATE()) * 1000
and t2.name = t1.name
)
GROUP BY t1.PROVIDER;