在有条件的大桌子上自我加入需要花费大量时间,优化查询

时间:2016-12-22 05:59:29

标签: mysql

我有一个包含详细信息的主表。

我希望在该会话中找到产品的所有组合,以及所有会话的特定会话中的所有其他产品。

create table combinations as 
select
    a.main_id,
    a.sub_id as sub_id_x,
    b.sub_id as sub_id_y,
    count(*) as count1,
    a.dates as rundate 
from
    master_table a 
    left join
        master_table b 
        on a.session_id = b.session_id 
        and a.visit_number = b.visit_number 
        and a.main_id = b.main_id 
        and a.sub_id != b.sub_id 
where
    a.sub_id is not null 
    and b.sub_id is not null 
group by
    a.main_id,
    a.sub_id,
    b.sub_id,
    rundate;

我对查询做了解释

+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+
|  1 | SIMPLE      | a     | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 298148 |    90.00 | Using where; Using temporary; Using filesort       |
|  1 | SIMPLE      | b     | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 298148 |     0.08 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+

主要问题是,我的主表包含8000万行。此查询执行时间超过24小时。

所有列都已编入索引,我正在进行自我加入。

首先创建一个类似的表'master_table_2',然后进行连接会使我的查询更快吗?

有没有办法优化查询时间?

1 个答案:

答案 0 :(得分:0)

由于您的表由很多行组成,如果连接查询未正确优化且WHERE子句未正确使用,则会花费大量时间。但优化的查询可以节省您的时间和精力。以下链接对连接查询及其事实的优化有一个很好的解释 - Optimization of Join Queries

@Marcus Adams已经提供了类似的答案here

另一个选项是您可以单独选择并在代码端处理以进行优化。但它仅适用于某些特定条件。您将不得不尝试比较两个进程(连接查询和代码结束执行)并检查性能。一旦使用这种方法,我的表现会更好。

假设连接查询如下所示 -

SELECT A.a1, B.b1, A.a2
FROM A
INNER JOIN B
ON A.a3=B.b3 
WHERE B.b3=C;

我想说的是从A和B单独查询满足必要条件,然后尝试从代码结束获得所需的结果。

<强> N.B。 :这是一种非正统的方式,并不能被视为适用于所有标准。

希望它有所帮助。