6

2 つのテーブルを結合する MySQL クエリがあります。最初のテーブルのコール ID を 2 番目のテーブルにマップする必要があります。2 番目のテーブルには呼び出し 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 に答える