Mysql 相对简单的查询速度非常慢。我做错了什么?

Mysql 相对简单的查询速度非常慢。我做错了什么?,mysql,sql,performance,subquery,left-join,Mysql,Sql,Performance,Subquery,Left Join,只涉及4个表,所以我不知道为什么在我的数据库上执行这项操作需要90多秒 records表中大约有300万条记录,但是软件中没有其他查询像这个查询那么慢。有许多复杂得多的查询比这个查询快得多,所以我知道我做错了什么 这确实产生了正确的结果,但速度太慢了。。我做错了什么 选择 r、 id为'id`, concatr.fname,,r.lname作为“申请人”, r、 添加了“应用程序时间”, concatrimr.city,,r.state为'city`, coalesceq.count,0表示“尝

只涉及4个表,所以我不知道为什么在我的数据库上执行这项操作需要90多秒

records表中大约有300万条记录,但是软件中没有其他查询像这个查询那么慢。有许多复杂得多的查询比这个查询快得多,所以我知道我做错了什么

这确实产生了正确的结果,但速度太慢了。。我做错了什么

选择 r、 id为'id`, concatr.fname,,r.lname作为“申请人”, r、 添加了“应用程序时间”, concatrimr.city,,r.state为'city`, coalesceq.count,0表示“尝试”, coalesceq.last_调用,0作为“last called”, null作为“已删除”` 来自myfreshp_crm记录r 左连接 选择rid,countrid作为count,maxcalled作为上次调用 从myfreshp_crm.cc_队列 其中status='called' 按rid分组 q上的q.rid=r.id 左连接 选择rid,maxtime作为应用程序 从myfreshp_crm.calendar 其中event='约会' 按rid分组 a.rid上的a=r.id 左连接 选择rid,maxsent as sent 从myfreshp_crm.cc_队列 按rid分组 c.rid上的c=r.id 哪里 r、 id不在从asap_黑名单中选择lead_id中 和聚结Q.计数,0<4 和 c、 已发送>UNIX_时间戳-60*60*24*28或 r、 添加>UNIX_时间戳-60*60*24*28 和 a、 appt不为空 和a.appta.appt 或 r、 来源='在线' 并且a.appt为空 explain的输出扩展了。。。详情如下:

+----+-------------+----------------+------+---------------+-------------+---------+-------------------+---------+----------+----------------------------------------------+
| id | select_type | table          | type | possible_keys | key         | key_len | ref               | rows    | filtered | Extra                                        |
+----+-------------+----------------+------+---------------+-------------+---------+-------------------+---------+----------+----------------------------------------------+
|  1 | PRIMARY     | r              | ALL  | added,source  | NULL        | NULL    | NULL              | 3436521 |   100.00 | Using where                                  |
|  1 | PRIMARY     | <derived2>     | ref  | <auto_key0>   | <auto_key0> | 4       | myfreshp_crm.r.id |      10 |   100.00 | Using where                                  |
|  1 | PRIMARY     | <derived3>     | ref  | <auto_key1>   | <auto_key1> | 4       | myfreshp_crm.r.id |      15 |   100.00 | Using where                                  |
|  1 | PRIMARY     | <derived4>     | ref  | <auto_key1>   | <auto_key1> | 4       | myfreshp_crm.r.id |      15 |   100.00 | Using where                                  |
|  5 | SUBQUERY    | asap_blacklist | ALL  | NULL          | NULL        | NULL    | NULL              |     287 |   100.00 | NULL                                         |
|  4 | DERIVED     | cc_queue       | ALL  | rid           | NULL        | NULL    | NULL              |   77090 |   100.00 | Using temporary; Using filesort              |
|  3 | DERIVED     | calendar       | ALL  | rid,event     | NULL        | NULL    | NULL              |  102750 |    97.15 | Using where; Using temporary; Using filesort |
|  2 | DERIVED     | cc_queue       | ALL  | rid,status    | NULL        | NULL    | NULL              |   77090 |    99.39 | Using where; Using temporary; Using filesort |
+----+-------------+----------------+------+---------------+-------------+---------+-------------------+---------+----------+----------------------------------------------+
8 rows in set, 1 warning (0.08 sec)
记录表:

创建表“记录” `id`int20非空自动增量, `uid`int20不为空, `cid`int20不为空, `vid`int8不为空, `添加了'int25 NOT NULL, `fname`varchar50不为空, `mname`varchar50不为空, `lname`varchar50不为空, `地址'varchar200不为空, `城市'varchar50不为空, `状态“varchar50”不为空, `zip`int5不为空, `phone1`varchar16不为空, `phone2`varchar16不为空, `mobilephone`varchar16不为空, `电子邮件'varchar100不为空, `状态'enum'active'、'inactive'、'followup'、'responsed'、'sell'、'dead'不为空, `ssn`varchar11不为空, `perm`enum'yes','no'不为空默认值'no', `打印标签'int30不为空, `打印字母'int30不为空, `dob`varchar20不为空, `源'varchar15非空默认值'imported', `选择退出'enum'no','yes'不为空默认值'no', `其他_数据`长文本不为空, `“int11”中的sms_opt_不为空, 主键'id`, 键'cid``cid`, 键'uid``uid`, 键'vid``vid`, 键'status`` status`, 键'uid_2``uid`, 键'printed_label`` printed_label`, 键'fname``fname`, 键'mname``mname`, 键'lname``lname`, 键'phone1``phone1`, 键'phone2``phone2`, 输入'printed\u letter`` printed\u letter`, 关键字“地址”``地址`, 关键城市城市, 键'state``state`, 键'added`` added`, 键`source``source`, 键'email``email`, 键'zip``zip`, 键'ssn``ssn`, 键'dob``dob` ENGINE=InnoDB AUTO_INCREMENT=8938455默认字符集=1 cc_队列表:

创建表“cc_队列” `id`int20非空自动增量, `rid`int20不为空, `已发送'int30非空, `称为'int30 NOT NULL, `原因'varchar150 COLLATE utf8\u unicode\u ci非空, `状态'enum'waiting','called'COLLATE utf8\u unicode\u ci NOT NULL, `处置`长文本整理utf8\u unicode\u ci不为空, `注释'varchar250 COLLATE utf8\u unicode\u ci NOT NULL, `sentToCC`int11不为空, 主键'id`, 键'rid``rid`, 键'status`` status`, 键`sent``sent`, 键`called`` called`, 键'sentToCC``sentToCC` ENGINE=MyISAM自动增量=77097默认字符集=utf8 COLLATE=utf8\U unicode\U ci 日历表:

创建“日历”表 `id`int11非空自动增量, `uid`int11不为空, `rid`int20不为空, `添加了'int25 NOT NULL, `时间'int11不为空, `事件'varchar500 COLLATE utf8\u unicode\u ci NOT NULL, `详细信息'varchar1000 COLLATE utf8\u unicode\u ci NOT NULL, 主键'id`, 键'uid``uid`, 键'rid``rid`, 键'added`` added`, 键'time``time`, 键'event``事件'333 ENGINE=MyISAM自动增量=151930默认字符集=utf8 COLLATE=utf8\U unicode\U ci asap_黑名单表:

创建表'asap_blacklist` `id`int11非空自动增量, `时间'int11不为空, `lead_id`int11不为空, 主键'id` ENGINE=InnoDB自动增量=1483默认字符集=utf8 COLLATE=utf8\U bin 下面是信息模式所说的

加入 子查询确实会对性能产生负面影响。 在可能的情况下,我将使用视图的连接替换这些连接

我发现,甚至像你在WHERE子句中的那句话。。。 r、 id不在从asap_黑名单中选择lead_id中 替换为以下内容时,速度会快得多: 左尽快加入BL.Lead\U ID=R.ID上的黑名单BL 和
BL.Lead_ID为空

连接到子查询确实会对性能产生不利影响。 在可能的情况下,我将使用视图的连接替换这些连接

我发现,甚至像你在WHERE子句中的那句话。。。 r、 id不在从asap_黑名单中选择lead_id中 替换为以下内容时,速度会快得多: 左尽快加入BL.Lead\U ID=R.ID上的黑名单BL 和
BL.Lead_ID为空

您可以简化代码

首先,您在myfreshp_crm.cc_队列中聚合两次,并将两个结果集分别加入myfreshp_crm.records,但您可以使用条件聚合进行一次聚合。 q和c别名子查询可以合并为以下内容:

SELECT rid, 
       COUNT(CASE WHENE status = 'called' THEN rid END) AS count, 
       MAX(CASE WHENE status = 'called' THEN called END) AS last_called,
       MAX(sent) AS sent
FROM myfreshp_crm.cc_queue
GROUP BY rid
还要简化WHERE子句中的条件

条件:

a.appt is not null and a.appt < UNIX_TIMESTAMP()
c.sent is not null and c.sent > a.appt
可以简化为:

c.sent > a.appt
因此,请尝试以下代码:

SELECT r.id AS `ID`,  
       CONCAT(r.fname, ' ', r.lname) AS `Applicant`,
       r.added `App Time`,
       CONCAT(trim(r.city), ', ', r.state) AS `City`, 
       COALESCE(q.count, 0) AS `Attempts`,
       COALESCE(q.last_called, 0) AS `Last Called`,
       NULL AS `Removed`
FROM myfreshp_crm.records r 
LEFT join (
  SELECT rid, 
         COUNT(CASE WHENE status = 'called' THEN rid END) AS count, 
         MAX(CASE WHENE status = 'called' THEN called END) AS last_called,
         MAX(sent) AS sent
  FROM myfreshp_crm.cc_queue
  GROUP BY rid
) q ON q.rid = r.id 
LEFT join (
  SELECT rid, MAX(time) AS appt
  FROM myfreshp_crm.calendar 
  WHERE event = 'Appointment' 
  GROUP BY rid
) a ON a.rid = r.id
WHERE r.id NOT IN (SELECT lead_id FROM asap_blacklist) 
  AND COALESCE(q.count, 0) < 4
  AND (q.sent > (UNIX_TIMESTAMP() - (60 * 60 * 24 * 28)) OR r.added > (UNIX_TIMESTAMP() - (60 * 60 * 24 * 28)))
  AND ((a.appt < UNIX_TIMESTAMP()  AND q.sent > a.appt) OR (r.source = 'Online'  AND a.appt is NULL)) 

您可以简化代码

首先,您在myfreshp_crm.cc_队列中聚合两次,并将两个结果集分别加入myfreshp_crm.records,但您可以使用条件聚合进行一次聚合。 q和c别名子查询可以合并为以下内容:

SELECT rid, 
       COUNT(CASE WHENE status = 'called' THEN rid END) AS count, 
       MAX(CASE WHENE status = 'called' THEN called END) AS last_called,
       MAX(sent) AS sent
FROM myfreshp_crm.cc_queue
GROUP BY rid
还要简化WHERE子句中的条件

条件:

a.appt is not null and a.appt < UNIX_TIMESTAMP()
c.sent is not null and c.sent > a.appt
可以简化为:

c.sent > a.appt
因此,请尝试以下代码:

SELECT r.id AS `ID`,  
       CONCAT(r.fname, ' ', r.lname) AS `Applicant`,
       r.added `App Time`,
       CONCAT(trim(r.city), ', ', r.state) AS `City`, 
       COALESCE(q.count, 0) AS `Attempts`,
       COALESCE(q.last_called, 0) AS `Last Called`,
       NULL AS `Removed`
FROM myfreshp_crm.records r 
LEFT join (
  SELECT rid, 
         COUNT(CASE WHENE status = 'called' THEN rid END) AS count, 
         MAX(CASE WHENE status = 'called' THEN called END) AS last_called,
         MAX(sent) AS sent
  FROM myfreshp_crm.cc_queue
  GROUP BY rid
) q ON q.rid = r.id 
LEFT join (
  SELECT rid, MAX(time) AS appt
  FROM myfreshp_crm.calendar 
  WHERE event = 'Appointment' 
  GROUP BY rid
) a ON a.rid = r.id
WHERE r.id NOT IN (SELECT lead_id FROM asap_blacklist) 
  AND COALESCE(q.count, 0) < 4
  AND (q.sent > (UNIX_TIMESTAMP() - (60 * 60 * 24 * 28)) OR r.added > (UNIX_TIMESTAMP() - (60 * 60 * 24 * 28)))
  AND ((a.appt < UNIX_TIMESTAMP()  AND q.sent > a.appt) OR (r.source = 'Online'  AND a.appt is NULL)) 
并去掉status、rid和event上相应的单列

AND r.id not in (select lead_id from asap_blacklist)

并去掉status、rid和event上相应的单列

AND r.id not in (select lead_id from asap_blacklist)


它可能是缺少的索引,请共享explain extended的结果我添加了output@eshirvana。它可能是缺少的索引,请共享explain extended的结果我添加了output@eshirvana.VIEWs是语法糖;它们不提供任何性能提升—甚至不提供物化视图?MySQL有这些吗?MySQL没有物化视图。除非你自己做,比如使用Trigger.Hmmm,从很久以前开始,我认为他们教我优化/编译视图,使它们比直接解释的SQL更快;它们不提供任何性能提升—甚至不提供物化视图?MySQL有这些吗?MySQL没有物化视图。除非你自己做,比如使用Trigger.Hmmm,从很久以前开始,我认为他们教我优化/编译视图,使它们比解释的直接SQL更快。这个答案加上@RickJames答案的后半部分将执行时间减少了近50%。等到我有更多的时间尝试使用索引,然后再选择对性能影响最大的答案。这个答案与@RickJames答案的后半部分结合起来,将执行时间减少了近50%。在选择对性能影响最大的答案之前,等待我有更多的时间尝试使用索引。