尽管有索引,但带有3个左联接的MySQL查询出乎意料的缓慢

问题描述 投票:0回答:2

此查询需要6分钟以上才能运行:

SELECT null as primary_id, t211.appln_id as appln_id,       t212.pat_publn_id,  t212.citn_id,       citn_origin,    cited_pat_publn_id, cited_appln_id,     pat_citn_seq_nr, relevant_claim,
    t212.cited_npl_publn_id,        npl_citn_seq_nr,    citn_gener_auth,    npl_biblio,     npl_type,           publn_nr_original,  t215.citn_categ, t215.CITN_REPLENISHED, npl_author, 
    npl_title1, npl_title2, npl_editor, npl_volume, npl_issue, npl_publn_date, npl_publn_end_date, npl_publisher, npl_page_first, npl_page_last,    npl_abstract_nr, npl_doi, npl_isbn, npl_issn, online_availability, online_classification, online_search_date
FROM 
                tls211_pat_publn    as t211 
    LEFT JOIN   tls212_citation     as t212 on t211.pat_publn_id = t212.pat_publn_id 
    LEFT JOIN   tls214_npl_publn    as t214 on t214.npl_publn_id = t212.cited_npl_publn_id
    LEFT JOIN   tls215_citn_categ   as t215 on t215.pat_publn_id = t212.pat_publn_id and t215.citn_id = t212.citn_id
    where t211.pat_publn_id=777;

此查询需要0秒才能运行:

SELECT null as primary_id, t211.appln_id as appln_id,       t212.pat_publn_id,  t212.citn_id,       citn_origin,    cited_pat_publn_id, cited_appln_id,     pat_citn_seq_nr, relevant_claim,
    t212.cited_npl_publn_id,        npl_citn_seq_nr,    citn_gener_auth,    npl_biblio,     npl_type,           publn_nr_original,  t215.citn_categ, t215.CITN_REPLENISHED, npl_author, 
    npl_title1, npl_title2, npl_editor, npl_volume, npl_issue, npl_publn_date, npl_publn_end_date, npl_publisher, npl_page_first, npl_page_last,    npl_abstract_nr, npl_doi, npl_isbn, npl_issn, online_availability, online_classification, online_search_date
FROM 
                tls211_pat_publn    as t211 
    LEFT JOIN   tls212_citation     as t212 on t211.pat_publn_id = t212.pat_publn_id 
    LEFT JOIN   tls214_npl_publn    as t214 on t214.npl_publn_id = t212.cited_npl_publn_id
    LEFT JOIN   tls215_citn_categ   as t215 on t215.pat_publn_id = t212.pat_publn_id 
    where t211.pat_publn_id=777;

唯一的区别是添加:and t215.citn_id = t212.citn_id在最后一个LEFT JOIN的末尾。

t212和t215都具有citn_id的索引。

我对此进行了“荒唐”的解释。这是最慢的解释:

+----+-------------+-------+------------+--------+-------------------------+-------------+---------+-------------------------------------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys           | key         | key_len | ref                                       | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+-------------------------+-------------+---------+-------------------------------------------+------+----------+-------------+
|  1 | SIMPLE      | t211  | NULL       | const  | PRIMARY                 | PRIMARY     | 4       | const                                     |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t212  | NULL       | ref    | PRIMARY,ppi             | ppi         | 4       | const                                     |    7 |   100.00 | NULL        |
|  1 | SIMPLE      | t214  | NULL       | eq_ref | PRIMARY                 | PRIMARY     | 4       | patstat_2019_fall.t212.cited_npl_publn_id |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t215  | NULL       | ref    | PRIMARY,idx_citn_id,ppi | idx_citn_id | 2       | patstat_2019_fall.t212.citn_id            |   11 |   100.00 | Using where |
+----+-------------+-------+------------+--------+-------------------------+-------------+---------+-------------------------------------------+------+----------+-------------+
4 rows in set, 1 warning (0.00 sec)

以下是快速解释:


+----+-------------+-------+------------+--------+---------------+---------+---------+-------------------------------------------+------+----------+-------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref                                       | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+---------+---------+-------------------------------------------+------+----------+-------+
|  1 | SIMPLE      | t211  | NULL       | const  | PRIMARY       | PRIMARY | 4       | const                                     |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | t212  | NULL       | ref    | PRIMARY,ppi   | ppi     | 4       | const                                     |    7 |   100.00 | NULL  |
|  1 | SIMPLE      | t214  | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | patstat_2019_fall.t212.cited_npl_publn_id |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | t215  | NULL       | ref    | PRIMARY,ppi   | ppi     | 4       | patstat_2019_fall.t212.pat_publn_id       |   47 |   100.00 | NULL  |
+----+-------------+-------+------------+--------+---------------+---------+---------+-------------------------------------------+------+----------+-------+
4 rows in set, 1 warning (0.02 sec)

[我看到慢的人在Extra栏中说“在哪里使用”。听起来不祥,但只说11行。

我的慢查询日志说:

Query_time: 269.658475  Lock_time: 0.000000 Rows_sent: 9  Rows_examined: 113106063

检查了很多行...但是我听不懂为什么。

我相信这对某人来说是显而易见的,但是我已经走到尽头了。

帮助?!

mysql
2个回答
2
投票

每个连接只能使用一个索引。如果pat_publn_idcitn_id具有单独的索引,则必须选择其中一个要使用,然后扫描另一列。

由于您要在两列上进行连接,因此要获得最有效的索引,您需要一个包含两列的多列索引。

ALTER TABLE tls212_citation ADD INDEX (pat_publn_id, citn_id);
ALTER TABLE tls215_citn_categ ADD INDEX (pat_publn_id, citn_id);

0
投票

citn_id在t212和t215中是否都具有单行条目?或t212具有单个条目,但t215具有多个条目。第二个原因导致速度问题。甚至查询也可能停止工作。

您需要检查一下,是否两个表都具有单个条目。

如果有多个条目,则左联接将不起作用。您需要以其他方式格式化SQL。

© www.soinside.com 2019 - 2024. All rights reserved.