6

我有一个连接两个表的 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    |                |
+----------------+----------------------+------+-----+---------+----------------+
4

1 回答 1

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);
于 2013-10-23T12:27:37.727 回答