MySQL离开加入很慢,而且通常会永远挂起

时间:2017-05-31 13:35:05

标签: mysql join

我有2个表,ticket_data和nps_data。

ticket_data保存一般IT问题信息,nps_data保存用户反馈。 表格的基本概念是:

ticket_data表。 aprox的。 1,500,000行:30个字段: ticket_number,logged_date,logged_team,resolution_date

上的索引
|ticket_number | logged_date | logged_team | resolution_date  |
| I00001       |  2017-01-01 | Help Desk   | 2017-01-02       |
| I00002       | 2017-02-01  | Help Desk   | 2017-03-01       |
| I00010       | 2017-03-04  | desktop sup | 2017-03-04       |

显然还有很多其他领域,但这就是我正在使用的

nps_data表 aprox 83,000行:10个字段: index ticket_number

|ticket_number | resolving team| q1_score|
| I00001       | helpdesk      | 5       |
| I00002       | desktop sup   | 0       |
| I00010       | desktop sup   | 10      |

当我做一个简单的查询,例如

select a.*, b.q1_score from
(select * from ticket_data
where resolution_date > '2017-01-01') a
left join nps_data b
on a.ticket_number = b.ticket_number

查询需要永远运行,当我这样说时,我的意思是我在10分钟后停止查询。 但是,如果我运行查询以使用名为ticket_details的表连接ticket_data,该表使用以下查询具有超过1,000,000行

select *
(select * from ticket_data
where resolution_date > '2017-01-01') a
left join ticket_details b
on a.ticket_number = b.ticket_number

查询大约需要1.3秒才能运行。

1 个答案:

答案 0 :(得分:0)

在上面的查询中,您有一个子查询,其别名a未在索引上运行。您正在查询未编入索引的字段resolution_date

简单的解决方法是为该字段添加索引。

票证编号 已编入索引。这可能就是为什么当你加入时,查询运行得更快。

进一步优化此方法的另一种方法是不要在子查询中执行select *(无论如何,这在生产系统中都是不好的做法)。它为DBMS创建了更多的开销,以便在子查询中传递所有结果。

另一种方法是对列进行部分索引,例如:

create index idx_tickets on ticket_data(ticket_number) where resolution_date > '2017-01-01'

但是,如果2017-01-01'的时间戳,我只会这样做。是一个永远使用的常数。

您还可以创建一个复合索引,因此查询引擎将运行Index Only Scan,从而直接从索引中提取数据,而无需返回到表中。

为了让我参考这个,我需要知道你在运行什么DBMS。

当然,所有这些都取决于您正在运行的DBMS类型。