我有一个MySQL查询,它连接在两个表之间。我需要将第一个表中的调用id映射到第二个表。第二个表可能没有调用id,因此我需要保持连接表。以下是查询,完成大约需要125秒。
select uniqueid, TRANTAB.DISP, TRANTAB.DIAL FROM
closer_log LEFT JOIN
(select call_uniqueId, sum(dispo_duration) as DISP, sum(dialing_duration) as DIAL
from agent_transition_log group by call_uniqueId) TRANTAB
on closer_log.uniqueid=TRANTAB.call_uniqueId;
以下是使用左连接的查询的解释输出。
+----+-------------+----------------------+-------+---------------+----------------------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+-------+---------------+----------------------------+---------+------+--------+-------------+
| 1 | PRIMARY | closer_log | index | NULL | uniqueid | 43 | NULL | 37409 | Using index |
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 32535 | |
| 2 | DERIVED | agent_transition_log | index | NULL | index_agent_transition_log | 43 | NULL | 159406 | |
+----+-------------+----------------------+-------+---------------+----------------------------+---------+------+--------+-------------+
如果我进行内部连接,则执行时间约为2秒。
select uniqueid, TRANTAB.DISP, TRANTAB.DIAL FROM
closer_log JOIN
(select call_uniqueId, sum(dispo_duration) as DISP, sum(dialing_duration) as DIAL
from agent_transition_log group by call_uniqueId) TRANTAB
on closer_log.uniqueid=TRANTAB.call_uniqueId;
使用内部联接解释查询输出。
+----+-------------+----------------------+-------+------------------------------------+----------------------------+---------+-----------------------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+-------+------------------------------------+----------------------------+---------+-----------------------+--------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 32535 | |
| 1 | PRIMARY | closer_log | ref | uniqueid,index_closer_log | index_closer_log | 43 | TRANTAB.call_uniqueId | 1 | Using where; Using index |
| 2 | DERIVED | agent_transition_log | index | NULL | index_agent_transition_log | 43 | NULL | 159406 | |
+----+-------------+----------------------+-------+------------------------------------+----------------------------+---------+-----------------------+--------+--------------------------+
我的问题是,为什么内部联接比左联接快得多。我的查询是否有任何导致执行缓慢的逻辑错误?我的优化选项有哪些?两个表中的调用ID都被编入索引。
编辑1)添加了表格说明
mysql> desc agent_transition_log;
+--------------------+----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+----------------------+------+-----+---------+-------+
| user_log_id | int(9) unsigned | NO | MUL | NULL | |
| event_time | datetime | YES | | NULL | |
| dispoStatus | varchar(6) | YES | | NULL | |
| call_uniqueId | varchar(40) | YES | MUL | NULL | |
| xfer_call_uid | varchar(40) | YES | | NULL | |
| pause_duration | smallint(5) unsigned | YES | | 0 | |
| wait_duration | smallint(5) unsigned | YES | | 0 | |
| dialing_duration | smallint(5) unsigned | YES | | 0 | |
| ring_wait_duration | smallint(5) unsigned | YES | | 0 | |
| talk_duration | smallint(5) unsigned | YES | | 0 | |
| dispo_duration | smallint(5) unsigned | YES | | 0 | |
| park_duration | smallint(5) unsigned | YES | | 0 | |
| rec_duration | smallint(5) unsigned | YES | | 0 | |
| xfer_wait_duration | smallint(5) unsigned | YES | | 0 | |
| logged_in_duration | smallint(5) unsigned | YES | | 0 | |
| sub_status | varchar(6) | YES | | NULL | |
+--------------------+----------------------+------+-----+---------+-------+
16 rows in set (0.00 sec)
mysql> desc closer_log;
+----------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+----------------------+------+-----+---------+----------------+
| closecallid | int(9) unsigned | NO | PRI | NULL | auto_increment |
| lead_id | int(9) unsigned | NO | MUL | NULL | |
| list_id | bigint(14) unsigned | YES | | NULL | |
| campaign_id | varchar(20) | YES | MUL | NULL | |
| call_date | datetime | YES | MUL | NULL | |
| start_epoch | int(10) unsigned | YES | | NULL | |
| end_epoch | int(10) unsigned | YES | | NULL | |
| length_in_sec | int(10) | YES | | NULL | |
| status | varchar(6) | YES | | NULL | |
| phone_code | varchar(10) | YES | | NULL | |
| phone_number | varchar(18) | YES | MUL | NULL | |
| user | varchar(20) | YES | | NULL | |
| comments | varchar(255) | YES | | NULL | |
| processed | enum('Y','N') | YES | | NULL | |
| queue_seconds | decimal(7,2) | YES | | 0.00 | |
| user_group | varchar(20) | YES | | NULL | |
| xfercallid | int(9) unsigned | YES | | NULL | |
| uniqueid | varchar(40) | YES | MUL | NULL | |
| callerid | varchar(40) | YES | | NULL | |
| agent_only | varchar(20) | YES | | | |
| queue_position | smallint(4) unsigned | YES | | 1 | |
| root_uid | varchar(40) | YES | | NULL | |
| parent_uid | varchar(40) | YES | | NULL | |
| extension | varchar(100) | YES | | NULL | |
| alt_dial | varchar(6) | YES | | NULL | |
| talk_duration | smallint(5) unsigned | YES | | 0 | |
| did_pattern | varchar(50) | YES | | NULL | |
+----------------+----------------------+------+-----+---------+----------------+
答案 0 :(得分:3)
左连接查找左边的字段+右边的不匹配的条目,因此必须检查右表中可能为NULL的每个连接字段(如果你没有关于该JOIN的字段的索引,它表示查询每次都会检查整个权限表。内部联接仅查找直接匹配,因此可能不必遍历整个表来执行联接(特别是如果您加入索引字段)。
顺便说一句,如果您只想显示agent_transition_log中提到的条目,则根本不需要加入:
select call_uniqueId, sum(dispo_duration) as DISP, sum(dialing_duration) as DIAL
from agent_transition_log group by call_uniqueId;
将完成这项工作。
或者,如果您确实想要添加缺少的条目:
SELECT call_uniqueId, sum(dispo_duration) as DISP, sum(dialing_duration) as DIAL
from agent_transition_log group by call_uniqueId
UNION
SELECT uniqueid as call_uniqueid, NULL as DISP, NULL as DIAL from closer_log
WHERE uniqueid not in (SELECT call_uniqueid FROM agent_transition_log);